Saturday, October 27, 2007

Getting SSH to Run in a Shell Loop

This is something I hear a lot, because it's still the norm for SSH.

A lot of times, you'll want to run a command remotely, and to do so expediently, you'll want to run that command in a shell loop. This works perfectly well for rsh (we're assuming for rsh that you've set up your .rhosts files and for SSH you have passwordless key exchange set up so these loops don't require user interaction):

for x in hosta hostb hostc
do
rsh $x "hostname" <----------- Or whatever command you want to run
done

This produces: hosta hostb hostc

That will run the command on every machine in your "for x" line and spit out the results. Interestingly enough, if you do this with SSH, only the first host will get processed, and the script will exit, producing only this: hosta

The issue here is with the way SSH deals with tty's. When that first loop terminates, SSH closes the tty and exits hard, breaking out of the script loop and terminating the script.

The solution is simple enough; just set up your SSH command so that it treats its terminal, in each invocation of the loop, as a "null terminal," like so (the "-n" option is available as a standard, but may vary depending on what release of SSH you're using):

for x in hosta hostb hostc
do
ssh -n $x "hostname"
done


Problem solved :)

I usually add a little extra to the end of the SSH line: ssh -n $x "hostname" 2>/dev/null

The "2>/dev/null" eliminates STDERR output so you don't have to see all the connect and disconnect information. It's useful for simple debugging, but, once your script is working okay, it's just more clutter.

Hopefully this will help you automate processes more securely and more easily in the future!

, Mike