2

I need to loop through and ssh to multiple hosts and run a series of commands on each.

something like:

for i in $(jot -w '%02.0f' 14 1)
>do ssh user@host$i sudo -i "command1; command2; command3"
>done

but I can't get it to work correctly. I've seen various things on The Google like sudo sh -c, piping to sudo, etc, but can't figure it out.

  • I'm ssh'ing as a regular user that can sudo with no password (ssh as root not enabled)
  • command1 not returning 0 should not prevent command2 from running, etc, hence ;
  • I'm running the loop from a mac, hence jot -w, which is roughly equivalent to seq -f in linux
  • ssh'ing to CentOS 5.4
  • I'd like it to run with root's $PATH so I don't have to specify the full path to the commands, but it's not totally necessary

thanks in advance!

carillonator
  • 815
  • 3
  • 12
  • 22
  • 1
    Bash alternatives to either 'jot' or `seq`: `printf '%02d ' {1..14}` or in Bash 4: `for i in {01..14}` (Bash < 4 ignores the leading zero). – Dennis Williamson Nov 17 '10 at 22:42

5 Answers5

6

Trying to pass quoted command strings over ssh is always a challenge. You don't mention what sort of error messages you're getting, but here are a few thoughts:

The default sudo configuration on many systems requires that your session have a valid TTY associated with it. This requires either (a) calling ssh with the "-t" option, or (b) remove the "requiretty" option from your sudo configuration.

This works for me (the destination is a set of RHEL5 systems):

for i in 0 1; do
  ssh -t host$i sudo -i "echo one; echo two; echo 'three four'"
done

This results in:

one
two
three four
Connection to host0 closed.
one
two
three four
Connection to host1 closed.

There are a variety of tools that will make your life easier if you do this sort of thing often:

And so forth. I usually just use shell scripts, myself.

larsks
  • 43,623
  • 14
  • 121
  • 180
  • 1
    Are you sure you have your command escaped right? When I run `ssh -t host sudo -i "/usr/bin/id; /usr/bin/id"` the results I get suggest that the second command is not privileged. – Zoredache Nov 17 '10 at 22:12
  • Zoredache is right, you need another layer of quotes/escapes or ssh will run `sudo -i echo one` and `echo two` etc as separate commands. Try: `ssh -t host$i "sudo -i 'id; echo \" three four\"; id'"` (that's three layers of quotes -- escaped double quotes [the arg to the echo command] inside single quotes [the command passed to sudo] inside double quotes [the command passed to ssh]). This can get arbitrarily confusing... – Gordon Davisson Nov 17 '10 at 22:34
6

I find that getting the quoting correct is pretty annoying. Instead I tend to just pass commands to bash on the remote host through a pipe instead. This way you don't have to worry about getting the escaping right in your ssh command line. Just pass into the pipe exactly what you would type if you were connected interactively.

CMDS="sudo bash -c '/usr/bin/id; /usr/bin/id; '/usr/bin/id"
for i in 0 1; do
  echo $CMDS | ssh -t host$i bash
done

Which returns

uid=0(root) gid=0(root) groups=0(root)
uid=0(root) gid=0(root) groups=0(root)
uid=0(root) gid=0(root) groups=0(root)
lcguida
  • 103
  • 3
Zoredache
  • 130,897
  • 41
  • 276
  • 420
1

I think pssh is what you need to work with.

adamo
  • 6,925
  • 3
  • 30
  • 58
0

http://sourceforge.net/projects/clusterssh/

This is a clear winner :D

Arenstar
  • 3,602
  • 2
  • 25
  • 34
0

Have a look at BatchLogin:

http://batchlogin.sourceforge.net/

BatchLogin is a free software (GPL) licensed tool that allows you to manage connections to servers in serial format across diverse environments. It has its limitations, but for the most part, any script or data file can be automatically transferred and executed across a multiple server environment, regardless of the complexity of the "zone" (I.E.: iDMZ, DMZ, etc). It does this in a way that shell scripts and access to servers can easily be managed on a "per admin" basis.

Hans
  • 160
  • 3