Question

my problem is as follows: I'm writing a script whose purpose is to run a certain scripts on different servers in parallel. I.e., I want to log into a remote server, enter the password (this is not negotiable because boss), starts the script, close the connection while the script is still running, connect to the next server and do the whole dance again. How do I do it?

Was it helpful?

Solution

Assuming bash is the target shell on all of the remote machines, you could do for one machine:

ssh user@host /path/to/script '&>/dev/null' '</dev/null' '&' disown

For multiple machines you could then script this like:

hosts='user1@host1 user2@host2'

for host in $hosts
do
  ssh $host /path/to/script '&>/dev/null' '</dev/null' '&' disown
done

This should just have you typing in passwords.

Alternatively if you can use the same password for multiple machines, I would recommend looking in to ClusterSSH. With this you can log into multiple machines simultaneously and type commands to be sent to all of them in a single window or in individually in each xterm window. This would save you typing the same password repeatedly. Once logged in you could run the command as above (without the ssh user@host part) and exit.

Update

Couple of extra thoughts here. First it probably isn't a great idea to discard the script output completely, since you will never know what happened if something went wrong. You could just put it in a file to look at later by replacing '&>/dev/null' with '&>filename'. Another approach would be to have the remote machine email it to you (provided it is properly set up to do this):

host=user@host
ssh $host \(/path/to/script '2>&1' \| mail -s "$host output" me@me.com\) \
  '&>/dev/null' '</dev/null' '&' disown

Second if the script is on the local host, you can copy it across and execute it in one command. Assumes a shell script, if not just replace sh with the correct interpretor)

</path/to/script ssh user@host \
  cat \>script \; sh ./script '&>/dev/null' '</dev/null' '&' disown

OTHER TIPS

After logging in you can use screen utility to start new terminal session and later detach from it, example:

[user@local]$ ssh machine
[user@machine]$ screen -S my_session
# you are now switched to new terminal session named "my_session"
# now you can start long operation, that you want to keep in background
[user@machine]$ yes
# press "Ctrl-a d" to detach, you will go back to original session
[detached from 11271.my_session]
# now you can leave ssh (your session with "yes" running will be kept in background)
# to list existing screen sessions run:
[user@machine]$ screen -list
There is a screen on:
11271.my_session    (Detached)
1 Socket in /var/run/screen/S-user.
# to re-attach use -r
[user@machine]$ screen -r my_session
# you will be back to session with "yes" still running (press Ctrl-C to stop it)

Once you will understand how screen works, you can try scripting it; this is how you start screen session in detached state running my_command:

$ screen -d -m my_command

expect can automate this pretty easily:

#!/usr/bin/expect -f

set hosts {your list of hosts goes here ...}
foreach host $hosts {
    spawn ssh -t user@$host screen ./script.sh
    expect "assword:"
    send -- "secret\r"
    sleep 1
    send -- "d"
    expect eof
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top