dish - tool for parallel sysadmin of multiple hosts
dish [option]... -e command {-g hosts_file |
host_1 host_2 ...}
dicp {-g hosts_file | -g "user@host_1 ..."}
local_file :remote_file
dicp {-g hosts_file | -g "user@host_1 ..."}
:remote_file local_file
dish - the diligence shell executes commands on several hosts via
ssh/rsh/telnet, and also makes easy the distribution of files by scp/rcp, a
remote password change, etc. It can process hosts in parallel mode.
- -h
- Print help message describing shortly all command-line options
- -H, --help
- Comprehensive help including examples
- --version
- Print program version and copyright message, then exit
- -V
- Display the version number and exit
- -C <dir>
- Configuration directory - $HOME/.dish is default; In this directory are
located following configuration files: 'hosts', 'rests', 'pass', and
'options'. When used, this option must be the first argument in the
command line string, or be the second one if `-D' chosen! Alternatively,
one can specify the configuration directory by defining the environment
variable DISH_CONF.
- -CC <dir>
- Same as `-C' with fallback to default if local config not found; This
means that, in case the files 'pass', 'options' or 'rests' are absent in
the given directory, but such files exist in $HOME/.dish, the latter will
be considered. The only exception is '$HOME/.dish/hosts' which will be
ignored. Using this option is equivalent to changing directory to the
opted one and then executing `dish'.
- -c <name>
- Program (alias "connector") and its options used for connecting
to the remote host(s) - for example `rsh', whereas the spawned process
will be "rsh $host <cmd>". Your default connector is
`ssh'. Furthermore, by using a relevant text-based client as connector,
one can access various kinds of hosts - switches, databases, and so
on.
- -e <cmd>
- Remote command to execute; It can be also set by the environment variable
DISH_CMD.
- -E <cmd>
- Execute command where also the connection part is specified e.g. "-E
'ssh $host date'" which is equal to "-e date". This option
is incompatible with `-c' and `-e'. It can be also set by the environment
variable DISH_FUEXE.
- -t
- Force pseudo-tty allocation in ssh; This happens automatically in case of
password change.
- -T <time>
- Timeout for command execution - default 30s (per host)
- -TT <time>
- Total timeout for command execution - default 300s (all hosts); This
option is useful only when hosts are processed in sequence and the total
processing time should not exceed the specified upper bound.
- -x <regex>
- Regular expression for the shell prompt; This value specifies which prompt
is to be expected in the program's shell after login into a system by
`telnet', `mysql', `sqlplus' or other interactive command-line clients
(see `-c'). The default value is `(%|\$|#|\>) ?$'.
- -X <regex>
- Regular expression for the password prompt; It is case-insensitive with
default value `Password: *$'.
- -AD <regex>
- Regular expression for the ssh-prompt to add a new host key - `connecting
(yes/no)?.*' is default
- -AC <str>
- String with the answer to the ssh-prompt to add a new host key - `yes' is
default
- -g <file>
- File with list of hosts/ip's/accounts to target; The command will be
executed on these targets. The default host file is '$HOME/.dish/hosts' -
normally per line one account of the form "user@host" (if ssh is
your choice for connector). In order to join lists use the option
repeatedly. Alternatively, the environment variable DISH_HOSTS could be
used to define the target hosts whereas in the specified string they have
to be separated by blanks. By combining this option with `-r' or `-i' you
can define various subsets of targeted hosts/accounts.
- -r <file>
- File with list of resting hosts/accounts to exclude; The default one is
'$HOME/.dish/rests'. A "resting host" means one which will be
excluded from the targets. The list of resting hosts or the file name
could be specified also by the environment variable DISH_RESTS.
- -i <file>
- File with list of hosts/accounts to overlap with targeted hosts; There is
no default file. Only overlapping hosts, such included in this list and at
the same time defined as targets, will be processed.
- -u <name>
- User name - default is your local user name; It can be defined also by the
environment variable DISH_USER. Internally the value is accessible by the
variable $user (see examples). Further, it is irrelevant in case that
accounts of the form "user@host" are processed since they
include already the user name.
- -p <passwd>
- Login password (-p "" = -pp = -a0) - alias "login
authentic" or "a0"; If no authentication for login is
required (no user- and no password-prompt appear), then use `/dev/null' as
password. If the user name is requested, yet the password is an empty
string, then `/dev/empty' has to be given as password. The value of this
option could be also a password file (see `-P'). Eventually, one can
define the password by the environment variable DISH_PASS.
- -a <passwd>
- Additional password for authentication (-a "" = -aa = -a1) -
alias "first authentic" or "a1"; Inside the spawn
process, if a program like `smbmount', `su', `ssh', etc. asks for
authentication, the a1-password is passed to it. This password can be also
set by the environment variable DISH_PASS1.
- -A <passwd>
- One more password for authentication (-A "" = -AA = -a2) - alias
"second authentic" or "a2"; When a spawned process,
after one authentication by the a1-password, asks again for a password,
then a2 is sent. This password can be also set by the environment variable
DISH_PASS2.
- -n <passwd>
- New password in case of password change (-n "" = -nn = -ne)
- -p0
- Login without authentication - the same as `-p /dev/null'
- -p1
- Set the a1-password to be the same as the login password; This option
should not be used together with `-p0' and `-a1'. See example d)
bellow.
- -P <file>
- File with password(s); The default password file is '$HOME/.dish/pass'. It
must be readable only for the user (file mode 600 or 700), otherwise the
program exits with error, but see also next option. Every line in the file
can hold a password entry of the form:
"password:username:hostname", alternatively
"password:::username:::hostname", or
"password;;;username;;;hostname". One can specify a list of
hosts separated by the `,' or `;' characters. Regular expressions for
hostnames are also allowed (see the example configuration files in the
distribution).
- -m
- Ignore the access permissions of the password file
- -s [<time>]
- Sequential processing of hosts (default mode); If a time interval
(measured in floating seconds) is specified, then the program is waiting
this amount of time before starting to process the next host in the
sequence.
- -F
- Spawn processes in background - fork and disconnect; This way all hosts
are processed essentially in parallel! It's a very powerful option -
depending on you RAM size and memory utilization, it shouldn't be a
problem to process a few hundreds of hosts in parallel. Anyway, be careful
- if you have too many hosts on the list, your could put your system under
load. The stdout's of the background processes are redirected to
'/dev/null', however you can use `-l' or `-L' to write the output to
files. See also 'bugs and known problems' in the manual page.
- -f
- Spawn processes in background without disconnecting from tty; It's the
same as `-F' whereas the stdout's of the spawned processes are sent to the
terminal. Also the parent process waits for his children to finish. See
also 'bugs and known problems' in the manual page.
- -q
- Be quiet - skip output from spawn and login; When working with the secure
shell, it is also convenient to use `ssh' with the `-q' option.
- -Q
- Be QUIET - skip any output
- -v
- Be verbose (default) - overrides `-q' and `-Q'
- -l <file>
- Log command output to file; The output of the spawned processes is
appended to the file.
- -L <name>
- Write a separate log for every host where <name> denotes the base
name of the log file. The full name of a log file is defined as
"<name>_<user@host>.log".
- -j
- Record the invoked command into a journal file with the name
'$HOME/.dish/journal'; It keeps the history of the executed commands and
their time of execution. An unique identifier is associated with every
command.
- -J
- Record the invoked command and the spawned processes as well; Write into
the journal file the executed command as well as the single processes
spawned and their time of execution.
- -o <file>
- File with command line options passed to the program - default is
'$HOME/.dish/options'; The options must be written in the file separated -
one per line. By means of this file, one can modify the standard
configuration: set up fork mode to be default, change the default
connector, and so forth. When working in "copy mode", i.e. by
invoking the program as 'dicp', '$HOME/.dish/options.dicp' is considered
to be the default options file.
- -d
- enable expect's diagnostic output (look at `man expect')
- -D
- Debug mode (dry-run); Print out environment variables, config file names,
and commands to execute, then exit. This option should be used as first in
the command line.
You should consider that the variables $host and $user are
evaluated. Thus $host changes dynamically its value to the actual
host/account name before a new process is spawned. The same is true for
$user.
a) Check the date and uptime on hosts 192.168.0.1 and
192.168.0.2
- dish -e 'date \; uptime' root@192.168.0.1 root@192.168.0.2
b) Distribute '.profile' and '.bashrc' to guest accounts on
'host1' and 'host2'
- dish -E "scp $HOME/.profile $HOME/.bashrc guest@\$host:" host1
host2
- or
- dicp -e "$HOME/.profile $HOME/.bashrc guest@:" host1 host2
- or
- dicp -g "host1 host2" $HOME/.profile $HOME/.bashrc guest@:
- or
- dicp -g "guest@host1 guest@host2" $HOME/.profile $HOME/.bashrc
:
c) Copy remote '.profile' files into the local directory on
localhost
- dicp -g "guest@host1 guest@host2 admin@host2" :.profile
.profile.\$host
- Here, the name of the target file (local file) will include the remote
account name in order that the local files have unique names.
d) Use `ssh' to login on 'host1' and copy from there '.profile' to
'host2'
- Since the list of hosts can not be empty, a dummy host is used to initiate
the process. The `-t' option is necessary to force pseudo-tty allocation
in `ssh', otherwise `ssh' will fail with error on login. A second password
(a1-password) is required for scp-authentication on 'host2':
- dish -a '' -E 'ssh -t user1@host1 scp .profile user2@host2:'
dummy_host
- In case the password of 'user1' and 'user2' is the same, you will be asked
only once for a login password for user1@host1 if you use `-p1':
- dish -p1 -E 'ssh -t user1@host1 scp .profile user2@host2:' dummy_host
- Or equivalently, and more simple:
- dish -p1 -t -e 'scp .profile user2@host2:' user1@host1
e) Substitute lines with `START_XNTPD=' by
`START_XNTPD="yes"' in /etc/rc.config
- This command is executed as root user on every host listed in
'Hosts.root':
- dish -u root -E 'ssh $user@$host "perl -pi -e
\"s/^START_XNTPD=.*\$/START_XNTPD=\\\"yes\\\"/g;\"
/etc/rc.config"' -g Hosts.root
f) Freeze accounts of users on a termination list
- By using a script called `FreezeUser.sh', all accounts of users found on
'Terminate.User.lst' will be frozen today at 24:00 o'clock on both server
groups as defined in files 'Hosts.1' and 'Hosts.2':
- dish -E 'ssh root@$host "cat Terminate.User.lst | while read UN; do
echo \"su - admin -c \\\$HOME/bin/FreezeUser.sh \$UN\" | at
24:00 ; done"' -g Hosts.1 -g Hosts.2
g) Print out remote configuration file of an automounter
- Login as 'admin' user on host 192.168.0.1, switch to 'root', then cat the
file '/etc/auto.net' and print out the date. The `-a' option causes the
program to ask you for the root-password on remote host:
- dish -u admin -a '' -E 'rsh -l $user $host su - root -c \"cat
/etc/auto.net\; date\"' 192.168.0.1
h) Install a package on Debian GNU/Linux hosts
- After mounting a fileserver over samba, install from there a debian
dish-package on all running servers, yet skip hosts on maintenance. Three
different passwords are needed for authentication - one for login, next
for su-root, and the last for mounting the fileserver:
- dish -a0 -a1 -a2 -g Debian.up -r Debian.maint -e 'su - -c \"mount -t
smbfs //FILESERVER/Packages.Dir /mnt/smb ; dpkg -i
/mnt/smb/dish_1.19.1_all.deb\"'
i) Check for system load >2 using default 'hosts' and 'pass'
config files
- dish '(uptime |egrep \" (\[2-9\]|1\[0-9\])\\.\" &&
hostname) |paste - -'
j) Query a MySQL database on remote host 10.0.0.1
- dish -pp -c 'mysql -p -u $user -h' -e 'use mysql; show tables; describe
user;' -u root 10.0.0.1
k) Change password concurrently on all hosts/accounts
- We assume that the list of user accounts is contained in file
'Accounts.lst', whereas an entry in the list is of the form
"user@hostname". After command execution, you will be asked
first for the login password (old password), and then for the new password
which eventually have to retyped correctly:
- dish -p '' -n '' -e passwd -g Accounts.lst
- Or alternatively, processing concurrently and quietly all hosts:
- dish -pp -nn -f -Q -e passwd -g Accounts.lst
- When you want to change password and use `-nn', then the a1-password is
implicitly set equal to the login password (a0-password).
l) Change password from 'root' account (don't use the `-a0'
option)
- If you are going to change the root-password on 'remotehost', then
try:
- dish -nn -e passwd root@remotehost
- The same as previous, but login as user 'admin' (login password), then
switch to 'root' (a1-password), and finally update the root-password:
- dish -a1 -nn -e 'su -c passwd' admin@remotehost
- Changing the password for 'admin' on 'localhost', after login as 'root'
via `telnet', is done by:
- dish -nn -c telnet -u root -e 'passwd admin' localhost
Notice that for password change, when `-p ""' (or
equivalently `-a0' or `-pp') is not explicitly used, the assumption is made
that `passwd' will not ask for the old password, as in case of a password
change by 'root'. The same is true also if you can login into an account
without typing a password, but then `passwd' prompts you to type the old one
- this situation occurs when one is using a ssh-key for login without
password-authentication. For such scenario the correct choice of options is
`-p0 -aa -nn'.
In case of properly prepared configuration files in '$HOME/.dish',
one can use dish as a distributed shell for a virtual cluster of hosts, and
run it without specifying any program parameters but merely issuing a
command, as for instance `dish df -k /' or `dicp .profile :'.
As a very last note, one should be aware that in case of
authentication by password, dish's automated login process is based on the
expectation that the login prompt send to the terminal will include the
case-insensitive regex-string `Password: *$' (but see also `-X'). Otherwise
the authentication procedure will fail.
If Tcl is compiled with thread support, the program hangs when
executed in parallel mode (options `-f' or `-F') - it seems to be a Tcl
problem. Generally, at present Debian GNU/Linux (and other debian-based
Linux distros as Ubuntu, Knoppix, etc.) pre-package Tcl with multi-thread
support enabled. Therefore, on such systems dish fails to process hosts in
parallel. In this case you can download the debian source package of Tcl,
remove the option "--enable-threads" in
´debian/rules´, rebuild the package with `dpkg-buildpackage
-rfakeroot', and eventually install it. It could be a good idea to put the
freshly installed package on hold. Otherwise, you should recompile it on
every tcl upgrade.
Report bugs to <gnu@mirendom.net>
Copyright © 2003-2013 Dimitar Ivanov
License: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it. There is NO
WARRANTY, to the extent permitted by law.