diff --git a/TODO b/TODO index 0fd8060..d4771a2 100644 --- a/TODO +++ b/TODO @@ -1,12 +1,19 @@ [NEW] -- +- Multiple hostfiles can now be passed via the -i option. The + argument can be the name of a single file or a quoted list of files. + The option can appear on the command line multiple times. + -H and -i can be used together to create custom host lists. [CHANGES] - The -H option can now appear on the command line multiple times thereby creating an aggregate list of all hosts named therein. +- Hostfiles must now be passed as an argument of -i. This was + done to provide a consistent way of passing multiple host + files on the commandline. + [BUG FIXES] - diff --git a/tsshbatch.py b/tsshbatch.py index 58d0e62..605c9ce 100755 --- a/tsshbatch.py +++ b/tsshbatch.py @@ -87,7 +87,7 @@ HOSTNOISE = '[%s]' HOSTLIST = 'Hosts' INDENTWIDTH = 8 -OPTIONSLIST = 'BC:EKG:H:NP:ST:abef:hkl:n:p:qstvxy' +OPTIONSLIST = 'BC:EKG:H:NP:ST:abef:hi:kl:n:p:qstvxy' PADWIDTH = 12 PATHDELIM = ':' PATHSEP = os.sep @@ -106,34 +106,35 @@ USAGE = \ PROGVER + "\n" +\ HOMEPAGE + "\n\n" +\ - "Usage: tsshbatch.py [-BEKNSTaehkqstvy -C configfile -G 'file dest' -P 'file dest' -f cmdfile -l logfile -n name -p pw ] -H 'host ..' | hostlistfile [command arg ... ]\n" +\ + "Usage: tsshbatch.py [-BEKNSTaehkqstvy -C configfile -G 'file dest' -P 'file dest' -f cmdfile -l logfile -n name -p pw ] -H 'host ..' -i 'hostfile ...' [command arg ... ]\n" +\ " where,\n" +\ "\n" +\ - " -B Print start and stop statistics (Off)\n" +\ - " -C configfile Specify location of ssh configuration file (~/.ssh/config)\n" +\ - " -E Write error output to stdout instead of stderr (Output to stderr)\n" +\ - " -K Force password prompting - Overrides previous -k\n" +\ - " -G 'file dest' GET file on host and write local dest directory\n" +\ - " -H '...' List of targeted hosts passed as a single argument\n" +\ - " -N Force prompting for username\n" +\ - " -P 'file dest' PUT local file to host dest directory\n" +\ - " -S Force prompting for sudo password\n" +\ - " -T seconds Timeout for ssh connection attempts (15 sec)\n" +\ - " -a Don't abort program after failed file transfers (Abort on failure)\n" +\ - " -b Don't abort program after failed sudo command (Abort on failure)\n" +\ - " -e Don't report remote host stderr output (Report host stderr) \n" +\ - " -f cmdfile Read commands from file\n" +\ - " -h Display help\n" +\ - " -k Use key exchange-based authentication (Use password auth)\n" +\ - " -l logfile Log errors to logfile (/dev/null)\n" +\ - " -n name Specify login name\n" +\ - " -p pw Specify login password\n" +\ - " -q Quiet mode - produce less 'noisy' output\n" +\ - " -s Silence all program noise - only return command output\n" +\ - " -t Run in test mode, don't actually execute commands (Default)\n" +\ - " -v Display extended program version information\n" +\ - " -x Turn off test mode (if on) and execute requests\n" +\ - " -y Turn on 'noisy' reporting for additional detail\n" + " -B Print start and stop statistics (Off)\n" +\ + " -C configfile Specify location of ssh configuration file (~/.ssh/config)\n" +\ + " -E Write error output to stdout instead of stderr (Output to stderr)\n" +\ + " -K Force password prompting - Overrides previous -k\n" +\ + " -G 'file dest' GET file on host and write local dest directory\n" +\ + " -H '...' List of targeted hosts passed as a single argument\n" +\ + " -N Force prompting for username\n" +\ + " -P 'file dest' PUT local file to host dest directory\n" +\ + " -S Force prompting for sudo password\n" +\ + " -T seconds Timeout for ssh connection attempts (15 sec)\n" +\ + " -a Don't abort program after failed file transfers (Abort on failure)\n" +\ + " -b Don't abort program after failed sudo command (Abort on failure)\n" +\ + " -e Don't report remote host stderr output (Report host stderr) \n" +\ + " -f cmdfile Read commands from file\n" +\ + " -h Display help\n" +\ + " -i 'file file...' Retrieve list of hosts from hostfile. Can be repeated.\n" +\ + " -k Use key exchange-based authentication (Use password auth)\n" +\ + " -l logfile Log errors to logfile (/dev/null)\n" +\ + " -n name Specify login name\n" +\ + " -p pw Specify login password\n" +\ + " -q Quiet mode - produce less 'noisy' output\n" +\ + " -s Silence all program noise - only return command output\n" +\ + " -t Run in test mode, don't actually execute commands (Default)\n" +\ + " -v Display extended program version information\n" +\ + " -x Turn off test mode (if on) and execute requests\n" +\ + " -y Turn on 'noisy' reporting for additional detail\n" ##### @@ -881,6 +882,10 @@ PrintStdout(USAGE) sys.exit() + if opt == "-i": + for hostfile in val.split(): + Hosts += ReadFile(hostfile, os.getenv(HOSTINCL), Hosts) + if opt == "-k": KEYEXCHANGE = True @@ -921,28 +926,14 @@ ##### -# Host & Command Line Command Definition Processing +# Command Line Command Definition Processing ##### -# Get the list of hosts if not specified on command line. -# The assumption is that the first argument is the file -# containing the list of targeted hosts and the remaining -# arguments form the command. +# Must have a list of hosts or we cannot go on with any +# operation whether file xfer or command execution if not Hosts: - - # Even if we are only doing file transfers and no command - # is specified, we have to have at least one argument here - # to tell us what hosts we're working on. - - if not args: - ErrorExit(eNOHOSTS) - - Hosts = ReadFile(args[0], os.getenv(HOSTINCL), Hosts) - command = " ".join(args[1:]) - -# If hosts were passed on the command line, all the arguments -# are understood to form the command. + ErrorExit(eNOHOSTS) else: command = " ".join(args[0:]) diff --git a/tsshbatch.rst b/tsshbatch.rst index f362afc..eb650a1 100644 --- a/tsshbatch.rst +++ b/tsshbatch.rst @@ -30,7 +30,7 @@ -------- :: - tsshbatch.py [-EKNSTaehkqstvxy -G 'file dest' -P 'file dest' -f cmdfile -l logfile -n name -p pw ] -H 'host ..' | hostlistfile [command arg ... ] + tsshbatch.py [-EKNSTaehkqstvxy -G 'file dest' -P 'file dest' -f cmdfile -l logfile -n name -p pw ] -H 'host ..' -i 'hostfile ...' [command arg ... ] DESCRIPTION ----------- @@ -90,7 +90,7 @@ the destination *directory* (on the local machine):: - tsshbatch.py -G "/foo/bar/baz /tmp" hostlist + tsshbatch.py -G "/foo/bar/baz /tmp" -i hostlist This copies ``/foo/bar/baz`` from every machine in ``hostlistfile`` to the local ``/tmp/`` directory. @@ -119,7 +119,7 @@ the local machine) to copy. The second, specifies the destination *directory* (on the remote machine):: - tsshbatch.py -P "/foo/bar/baz /tmp" hostlist + tsshbatch.py -P "/foo/bar/baz /tmp" -i hostlist This copies ``/foo/bar/baz`` on the local machine to ``/tmp/`` on every host in ``hostlist``. @@ -188,13 +188,6 @@ lines and thus no context information. Turns off ``-q``. -If the ``-H`` option is not selected, the item immediately following -the options is understood to be the name of the ``hostlistfile``. -This is a file that contains the name of each host - one per line - on -which to run the commands. This file can be commented freely with the -``#`` character. Leading- and trailing whitespace on a line are -ignored. - The last entry on the command line is optional and defines a command to run. ``tsshbatch`` will attempt to execute it on every host you've specified either via ``-H`` or a ``hostlistfile``:: @@ -398,9 +391,9 @@ MYPW=`cat mysecretpw | gpg` # User will be prompted for unlock passphrase - tsshbatch.py -n joe.luser -p $MYPW hostlist1 command1 arg - tsshbatch.py -n joe.luser -p $MYPW hostlist2 command2 arg - tsshbatch.py -n joe.luser -p $MYPW hostlist3 command3 arg + tsshbatch.py -n joe.luser -p $MYPW -i hostlist1 command1 arg + tsshbatch.py -n joe.luser -p $MYPW -i hostlist2 command2 arg + tsshbatch.py -n joe.luser -p $MYPW -i hostlist3 command3 arg This approach is best when you want your login credentials available for the duration of *the execution of a script*. It @@ -516,7 +509,7 @@ outstanding command (if any) at the end of the command line. This permits things like renaming on the remote machine after a ``PUT``:: - tsshbatch.py -P "foo ./" hostlist mv -v foo foo.has.a.new.name + tsshbatch.py -P "foo ./" -i hostlist mv -v foo foo.has.a.new.name ``GETs`` are a bit of a different story because you are retrieving a file of the same name on every host. To avoid having all but the last @@ -715,8 +708,8 @@ - In file transfer specifications:: - tsshbatch.py -xP"./fstab-__MYHOSTNAME__ ./" hostlist - tsshbatch.py -xG"/etc/__OSNAME__-release ./" hostlist + tsshbatch.py -xP"./fstab-__MYHOSTNAME__ ./" -i hostlist + tsshbatch.py -xG"/etc/__OSNAME__-release ./" -i hostlist - In ``cmdfiles``::