NAME¶
dish - tool for parallel sysadmin of multiple hosts
SYNOPSIS¶
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
DESCRIPTION¶
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.
OPTIONS¶
  - -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>
 
  - Command to execute
 
  - -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'.
 
  - -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 setting an environment variable: export
      DISH_PASS=<password>
 
  - -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.
 
  - -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.
 
  - -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 of the form
      "password[:username[:host]]". One can specify a list of hosts
      separated by the `,' or `;' characters. Regular expressions for host names
      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.
 
EXAMPLES¶
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.18.3_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.
BUGS AND KNOWN PROBLEMS¶
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.
REPORTING BUGS¶
Report bugs to <gnu@mirendom.net>
COPYRIGHT¶
Copyright © 2003-2012 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.
SEE ALSO¶
expect(1), tcl(3), 
ssh(1), 
rsh(1), 
telnet(1)