The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

mrsh - Mr. Shell runs a command on multiple hosts

SYNOPSIS

mrsh [options] [--] command
    --version -v: print the version, help, and exit
    --help    -h: print extended help and exit

    --host    -H: specify a host or group to run commands on
    --conf    -c: specify config file location, or skip configs
    --log     -l: specify a logfile location
    --trunc   -t: overwrite logfile, rather than append
    --shell   -s: change the (remote-)shell command
    --noesc   -N: do not escape the sub commands during host-routing mode
    --groups  -g: show groups and exit
    --list      : (nickname for --groups)
    --          : not strictly an option, but good to put before commands

DESCRIPTION

The -H has some special magic concerning "[groups]". If a group is specified before any other options or options arguments arguments (but possibly after other groups), it will automatically be expanded to have an imaginary -H before it. Example:

# list /tmp on all the hosts in @gr1
mrsh @gr1 -- ls -al /tmp

# list /tmp on all the hosts in @gr1 with a logfile
mrsh --log logfile @gr1 -- ls -al /tmp
--

Sometimes the option processor get confused by switches and options for the command being sent to the remote hosts. -- tells the options parser to quit looking.

--groups -g --list

List the groups and their hosts and exit. Will use groups listed in -H switches if applicable (ignoring -H arguments that are not groups).

--host -H

Names of hosts or "[groups]" upon which to run commands. Groups are prefixed with an @ character and can only be specified in the configuration file (see "CONFIG FILE").

Host and group specifications that overlap are reduced to a unique set, so if @localhosts contains host1 and @desktops contains host1, and for whatever reason -H host1 is also specified on the command line ... host1 will only appear in the hosts list just the one time.

Hostnames may be subtracted from any lists provided (via groups or -H) by prefixing the hostname (but not group) with -.

For instance, if @hosts contains a host named host1> and host1> is unavailable, users might type something like this:

mrsh @hosts -H-host1 uptime
--conf -c

By default, mrsh will look for .mrshrc the user's home directory. Users may change the location with this switch. The switch takes an optoinal argument, the location. When a location is not specified, it disables the loading of any config files.

Caveat: careful that -c doesn't slurp up the next word on the command line. It wants to eat your arguments.

--log -l --trunc -t

mrsh doesn't keep any logs by default. Users may specify a logfile location to start logging. Logs will be appended (even between runs) unless the truncate option is specified -- in which case, the logfile will simply be overwritten instead.

--shell -s

By default, mrsh uses the following command as the shell command.

ssh -o BatchMode yes -o StrictHostKeyChecking no -o ConnectTimeout 20 [%u]-l []%u %h

The %h will be replaced by the hostname(s) during execution (see "COMMAND ESCAPES").

Almost any shell command will work, see t/05_touch_things.t in the distribution for using perl as a "shell" to touch files. Arguments to -s are space delimited but understand very simple quoting:

--noesc -N

During host routing mode, mrsh will escape spaces and backslashes in a way that openssh (http://openssh.com/) will understand correctly. That behavior can be completely disabled with this option.

COMMAND ESCAPES

These things will be replaced before forking the commands on the remote hosts. There aren't many of these yet, but there will likely be more in the future.

%c

The command number.

%h

The hostname. The hostname escape supports a special host routing protocol. Hostnames that contain the routing character will be expanded to magically create sub-commands as needed to connect through hosts while executing commands.

When expanding a host route, all %h will be replaced with the elements of the command array up to that escape, plus the hostname, for each host in the hosts route.

This expansion also optionally (see -N above) expands spaces and slashes to escaped values compatible with openssh (http://openssh.com/).

This is perhaps more clear by example.

Let's say this is the command in question.

ssh -o 'BatchMode Yes' %h 'ls -ald /tmp/'

And let's say our hostname is corky!wisp, then the command becomes:

ssh -o 'BatchMode Yes' corky ssh -o 'Batchmode\ Yes' wisp 'ls\\ -ald\\ /tmp'
%u

Replaced with the username, if applicable. When hostname contains an @ character, for example jettero@corky, the portion before the @ is considered a username.

conditional replacement

If an element in a command exists in the form [%u]-l, then the argument -l will only appear in the argument list when %u has a value. If an arguemnt of the form []%u ([%u]%u works identically), it will only appear in the argument list when %u has a value.

The following command is expanded as follows for jettero@corky and corky respectively.

ssh [%u]-l []%u %h
ssh -l jettero corky # for jettero@corky
ssh corky            # for corky

CONFIG FILE

The config file is loaded using the Config::Tiny module, which supports basic "standard" .ini files. mrsh reads two sections for values and ignores all values it doesn't understand.

[options]

default-hosts

When no hosts are specified for a command, mrsh will seek to use these hosts and "[groups]" instead.

shell-command

This is the above -s setting, which allows changing the shell command.

no-command-escapes

This is the above -N setting, which disables escaping of arguments during host-routing mode.

[groups]

The [groups] section can contain as many hostname values as ... your platform as memory. Groups are expanded by pre-fixing with an @ character when passing hostnames to -H or via the default-hosts option above.

Hosts and host routes are space separated.

If a group contains references to other groups, it will automatically be recursively replaced. This recursion naively assumes there are no loops, but automatically stops about 30 deep. If you get unexpected results, this could be the problem.

EXAMPLE CONFIG

[options]
    default-hosts = @debian-desktops
    shell-command = ssh -o 'BatchMode Yes' [%u]-l []%u %h

[groups]
    debian-desktops = wisp corky razor

AUTHOR

Paul Miller <jettero@cpan.org

http://github.com/jettero

THANKS

Dennis Boone -- http://github.com/drboone

COPYRIGHT

Copyright 2009-2010 - Paul Miller

Released as GPL, like the original Mr. Shell circa 1997.

SEE ALSO

ssh(1), perl(1), App::MrShell, POE, POE::Wheel::Run