LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Multiple scp/ssh in one bash script (http://www.linuxquestions.org/questions/programming-9/multiple-scp-ssh-in-one-bash-script-836919/)

Lovelyhard 10-08-2010 05:21 AM

Multiple scp/ssh in one bash script
 
for updating several devices connected via IP I want to write a little bash script doing several scp and ssh commands, like

<pseudocode>
read -s -p "enter master pwd for devices:" inputline
devpwd=$inputline

scp $2 up@$1/tmp/
ssh up@$1 '/tmp/makeup.sh && reboot'

</pseudocode>

Unfortunately I have to enter the device's pwd for each scp/ssh call.
Is there a way to read the pwd ONCE via script and then distributing it via $devpwd ???

Yes, I know about key authentication, and, no, there is no way using this :-( All I found are well-meant ideas how to install key authentication. Yes, I know about possible security risks and, no, I do NOT want to store pwds in files ;-)

Any ideas how I can avoid entering the pwd again and again?
TIA,
Heinz

angel115 10-08-2010 05:33 AM

Please discard the post below I miss read you post...

Have you try a key exchange?
From the server that will run the script, like this:
Code:

ssh-copy-id -i ~/.ssh/id_rsa.pub username@remote-server
this will copy your key to the remote server and grant you access without password in a relatively secure way ;)

GrapefruiTgirl 10-08-2010 05:39 AM

I like the above idea, but given that the OP says he/she doesn't want to use key authentication, I think it would be a good job for `expect`.
Since I'm not good at writing `expect` scripts from scratch, if it were me I would use `autoexpect` to generate a working `expect` script that logs into one device and performs the needed tasks; then I would expand the script (mostly just copy & paste) to make it repeat the operations for the remaining machines.
Assuming the password is the same for all machines (hence the name "master password") you would just need to input the password one time to the script, and the script would re-use it to log into the second and subsequent machines.

If OP wants to investigate this route, check the manpage for `autoexpect` (and for `expect` also) - it's pretty complete as manpages go, and should give you an idea if it's the tool for this job.

Best regards.

ntubski 10-08-2010 11:34 AM

Expect isn't needed, use the ControlPath and ControlMaster options:
Code:

# will ask for password here
ssh -NfM -o 'ControlPath=~/.ssh/%r@%h:%p.conn' "$HOST"

# uses existing connection, doesn't ask for password
scp -o 'ControlPath=~/.ssh/%r@%h:%p.conn' $2 up@$HOST/tmp/
ssh -o 'ControlPath=~/.ssh/%r@%h:%p.conn' up@$HOST '/tmp/makeup.sh && reboot'

# close the connection
ssh -o 'ControlPath=~/.ssh/%r@%h:%p.conn' -O exit "$HOST"


Lovelyhard 10-12-2010 05:59 AM

I thought I would come around using expect and similar, anyway, it was exact what finally did the trick.

Thanks to all for your hints and input!

Heinz

GrapefruiTgirl 10-14-2010 05:03 AM

Hello Heinz,

glad you got a working solution! Did you write it in `expect` or use `autoexpect` or both?

If perchance you get a few minutes sometime, maybe you would show us the code you came up with - someone else might find it handy one day. :)

Thanks, and best regards!

Lovelyhard 10-15-2010 04:30 AM

I've done with a mixture of bash/expect.

What I've been searching for is the possibility to do the exact same procedure to a set of IP devices, e.g. reconfiguring by changing a config file and restarting a deamon, uploading a new flash image and calling an internal reflash procedure, ...

With a little help I got this, I've stripped all unneeded for better understanding what I did:
Code:

#!/bin/bash

read -s -p "Enter device password: " inputline
devpwd="$inputline\n"
filetomove=$1
devip=$2

echo -n "Startinf file transfer..."
res=$(expect -c "
  spawn scp $filetomove root@$devip:/control
  expect *password: { send $devpwd }
  expect *100%* { }
  exit
")
echo "Done. "
echo -n "Starting reconfigure..."
res=$(expect -d -c "
  spawn ssh root@$devip reconfigure
  expect *password: { send $devpwd }
  exit
")

I thougt it WOULD work like a charm, but only the first part did. The second failed, I've tricked myself by switching between two configs for testing... :-(. The command passed along ssh had never been executed.
But when I' echoing the ssh line to console ( using expect's -d parameter), and execiting it from the prompt it does exact what I'm expecting :-s

So I've changed the second part to:
Code:

res=$(expect -d -c "
  spawn ssh root@$devip
  expect *password: { send $devpwd }
  expect *dev>? { send reconfigure }
  exit
")

And this one is nagging cause of a pile of lines after successful login before the prompt appears.

The "most pretty" way for me would be to get the first attempt running; but, if second would make it - is there a simple possibility to "loop" thru an unknown number of incoming lines, just waiting/watching for the prompt?

BTW, I've used the notation given above cause doing it this way it's much easier using $variable from script without chinning the bar.

Any ideas?

heinz

Lovelyhard 10-15-2010 10:44 AM

*ARGL*

Double booboo!

First I've forgotten to add a "\n" at the end of my command strings, and second the prompt isn't "dev>" but "dev> " - which of course has never been found due to the trailing space... :-%

Add'lly I've changed the syntax a little bit, still using embedded expect code in the bash script (due to much easier access to script variables.
Code:

/usr/bin/expect - << EndMark
  ...
  ...
  ...
EndMark

This gives me the benefit to be able to use standard "..." string notation for send and expect which was a debacle in the previous version, too.

Heinz

johnc10 02-14-2011 06:03 AM

scp and ssh using expect within a bash script
 
I couldn't get the EndMark syle to work. Used this instead :-

Code:

#!/bin/bash

ssh1()
{
# ssh1 user server password command
# password is read in using $sshpassword
# e.g. ssh user1 test.server.com $sshpassword uname -a

# Use the following before calling scp1 and/or the server loop if have same password
#stty -echo
#echo "Enter password: "
#read sshpassword
#stty echo

expect -c "
  set timeout 1
  spawn ssh $1@$2 $4 $5 $6 $7 $8
  expect yes/no { send yes\r ; exp_continue }
  expect password: { send $3\r }
  expect .* {}
  exit
"
}

scp1()
{
# scp1 user server password file dir filecopy
# password is read in using $sshpassword
# e.g. scp1 user1 test.server.com $sshpassword myfile /tmp myfilecopy


# Use the following before calling scp1 and/or the server loop if have same password
#stty -echo
#echo "Enter password: "
#read sshpassword
#stty echo


expect -c "
  set timeout 1
  spawn scp $4 $1@$2:$5/$6
  expect yes/no { send yes\r ; exp_continue }
  expect password: { send $3\r }
  expect 100%
  sleep 1
  exit
"
}


stty -echo
echo "Enter password: "
read sshpassword
stty echo

scp1 user1 localhost $sshpassword file1 /tmp filecopy1
ssh1 user1 localhost $sshpassword uname -a


Reuti 02-15-2011 01:55 AM

The thread is some months old - I wonder about the OP's statement not to use an ssh-key. A passphrase protected ssh-key can be added to the ssh-agent at the start, and removed again when you are done.

Another option could be hostbased authentication.

johnc10 02-15-2011 02:49 AM

Yes key exchange is the best way, but this is not always possible as everyone logging on needs to have a key setup, so this is a alternative without storing the password in a script (and assumes all the servers have the same password).

johnc10 02-16-2011 10:40 AM

expect 100% needs sleep
 
Updated code above to add a sleep 1 after expect 100% . This is because the file transfer was being ended before all the file had actually transferred, therefore the 100% is being displayed prematurely (probably milliseconds).

Code:

expect -c "
  set timeout 1
  spawn scp $4 $1@$2:$5/$6
  expect yes/no { send yes\r ; exp_continue }
  expect password: { send $3\r }
  expect 100%
  sleep 1
  exit
"


ksdeiva 07-31-2012 09:33 AM

need your help
 
Hi, I have tried the script. its working good for local host i tried change the localhost and gave IP its not working...

please help me....





Quote:

Originally Posted by johnc10 (Post 4257794)
I couldn't get the EndMark syle to work. Used this instead :-

Code:

#!/bin/bash

ssh1()
{
# ssh1 user server password command
# password is read in using $sshpassword
# e.g. ssh user1 test.server.com $sshpassword uname -a

# Use the following before calling scp1 and/or the server loop if have same password
#stty -echo
#echo "Enter password: "
#read sshpassword
#stty echo

expect -c "
  set timeout 1
  spawn ssh $1@$2 $4 $5 $6 $7 $8
  expect yes/no { send yes\r ; exp_continue }
  expect password: { send $3\r }
  expect .* {}
  exit
"
}

scp1()
{
# scp1 user server password file dir filecopy
# password is read in using $sshpassword
# e.g. scp1 user1 test.server.com $sshpassword myfile /tmp myfilecopy


# Use the following before calling scp1 and/or the server loop if have same password
#stty -echo
#echo "Enter password: "
#read sshpassword
#stty echo


expect -c "
  set timeout 1
  spawn scp $4 $1@$2:$5/$6
  expect yes/no { send yes\r ; exp_continue }
  expect password: { send $3\r }
  expect 100%
  sleep 1
  exit
"
}


stty -echo
echo "Enter password: "
read sshpassword
stty echo

scp1 user1 localhost $sshpassword file1 /tmp filecopy1
ssh1 user1 localhost $sshpassword uname -a



ksdeiva 07-31-2012 09:37 AM

Multiple scp/ssh in one bash script using Spawn
 
Can anyone help me to execute multiple command using spawn like

1) first I have to copy file through SCP
2) Second, I have to execute a command (service restart)

Using Spawn ..


All times are GMT -5. The time now is 09:15 AM.