pax_global_header00006660000000000000000000000064136422733240014520gustar00rootroot0000000000000052 comment=2dce3d8e45a492985fa1ae0207b6d55afac97c16 pssh-2.3.4/000077500000000000000000000000001364227332400125035ustar00rootroot00000000000000pssh-2.3.4/.gitignore000066400000000000000000000000061364227332400144670ustar00rootroot00000000000000*.pyc pssh-2.3.4/AUTHORS000066400000000000000000000001471364227332400135550ustar00rootroot00000000000000依云 Andrew McNabb Brent Chun pssh-2.3.4/COPYING000066400000000000000000000030771364227332400135450ustar00rootroot00000000000000Copyright (c) 2018, Jeffrey Lund Copyright (c) 2016-2017, lilydjwg Copyright (c) 2009-2012, Andrew McNabb Copyright (c) 2003-2008, Brent N. Chun All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pssh-2.3.4/ChangeLog000066400000000000000000000240301364227332400142540ustar00rootroot000000000000002020-04-05 依云 * Version 2.3.4 - Add -g/--host-glob option, which accepts a glob to match in hosts - Fixes 2018-09-29 Jeffrey Lund * Version 2.3.3 - Added PSSH_NUMNODES enviroment variable - Added pardo helpers to psshlib 2017-09-14 依云 * Version 2.3.2 - Remove support for Python 2.4 - Many small fixes and code cleanup 2012-02-02 Andrew McNabb * Version 2.3.1 - Fixed a problem where man pages were omitted from the tar file. - Note that this release makes no changes to the programs. 2012-01-24 Andrew McNabb * Version 2.3 - Added a --inline-stdout option (issue #57). Thanks to pablo.barbachano for the patch. - Added a PSSH_HOST environment variable (issue #62). - Added a --version option (issues #33 and #45). - Expanded the pssh man page and added man pages for all other commands (issues #10 and #55). - Fixed askpass on Mac OS X 10.6.7 (issue #50). - Many other small fixes. 2011-02-02 Andrew McNabb * Version 2.2.2 - Fixed two crashes (issues 35 and 36). One affects Python <= 2.5 and the other affects all of the scripts except pssh. 2011-01-26 Andrew McNabb * Version 2.2.1 - Fixed a crash when the -l option was used in conjunction with a hosts file (issue #34). 2011-01-21 Andrew McNabb * Version 2.2 - Added a basic man page for pssh (issue #10). - Fixed askpass to work correctly in the presence of non-password prompts from ssh (issue #23). - Updated the -O option so that it can be specified multiple times (issue #25). Thanks to soham.mehta for the patch. - Fixed host file loader to give an error instead of a backtrace if a file is not found. - Fixed prsync's "-ssh-args" mangling of its argument (issue #24). Thanks to jbyers for the patch. - Fixed some variable names to appease pylint. Thanks to solj for the patch. - Improved pscp to be able to copy multiple local files. Thanks to Carlo Marcelo Arenas Belon for the patch. - Deprecated the PSSH_HOSTS environment variable that seems to cause more problems than it's worth. - Added the ability to set multiple hosts with a single -H flag (issue #26). Thanks to ilya@sukhanov.net for the patch. - Stopped passing "-q" to ssh by default (this masked error messages and reduced usability). - Removed automatic reading from stdin (deprecated in version 2.1). Please use the "-I" option instead. - Added meaningful exit status codes (issue #30). - Other minor fixes 2010-02-26 Andrew McNabb * Version 2.1.1 - Fixed a problem causing PSSH to crash with Python 2.4. 2010-02-24 Andrew McNabb * Version 2.1 - Added support for Python 3.0 and 3.1. Although PSSH has only been lightly tested with Python 3, anything that doesn't work in Python 3 is officially a bug. - Added a "-H" option for specifying hosts one-by-one instead of or in addition to a hosts file. - Added "-x" and "-X" options for passing extra command-line arguments to ssh and rsync. Also added a "-S" option to prsync for the special case of passing extra arguments to ssh (issue #2). - Added a "-I" option for specifying that pssh should read from standard input, and added a deprecation warning when standard input is used without this option (issue #12). - Made the command argument optional when the "-I" option is given, so a script can be passed to pssh on standard input (issue #5). - If a username or port is given, these are now included in the output filename, which allows different connections to be distinguished from each other (issue #7). - Added the pssh-askpass wrapper as a standalone script because setup.py was removing the executable bit from askpass.py. This fixes a "permission denied" error when using the -A option (issue #8). - Fixed a problem where pssh was unnecessarily specifying a username (issue #14). - Fixed a delay due to a lost SIGCHLD signal. - Removed extra spaces between output chunks in outdir files (issue #6). Thanks to knutsen for the fix. - Fixed a bug where pscp passed the wrong option for sending scp a custom port. Thanks to Jan Rafaj for the patch. - Fixed prsync to send the port as an option to ssh (issue #1). Thanks to Ryan Brothers for the fix. 2009-10-20 Andrew McNabb * Version 2.0 - Rewrote communication code to be more efficient. PSSH now operates with only one or two threads. - Added the ability to interrupt PSSH (with CTRL-c). - Added an option to prompt for a password. - Refactored code into a distinct library (psshlib). 2008-10-12 Brent N. Chun * Version 1.4.3 - Fixed bug in select_wrap. If timeout is None (e.g., the default for prsync, etc.), then never time out. Bug reported by Carlo Marcelo Arenas Belon (carenas at sajinet.com.pe). - Catch getopt exceptions and print usage as well as getopt exception string. Contribution from Carlo Marcelo Arenas Belon (carenas at sajinet.com.pe). - Added contribution from Bas van der Vlies (basv at sara.nl) to allow comments in hosts file. Comments must begin with # character (leading whitespace is also allowed). - Restore file status bugs after reading stdin in pssh. - Fixed typo bug in pslurp when using options and in non-recursive mode. - Removed conflicts with built-in names. 2008-09-01 Brent N. Chun * Version 1.4.2 - Fixed minor bug: select returns select.error on an error, not OSError. 2008-08-27 Brent N. Chun * Version 1.4.1 - Removed broken SIGCHLD handler. - Refining subprocess _cleanup dynamically to an empty lambda function since subprocess is not thread-safe and we already call wait on child processes ourselves anyway. - Adding missing verbose flag to rest of bin/* programs. 2008-08-24 Brent N. Chun * Version 1.4.0 - Fixed 64-bit bug in pslurp, pscp, prsync. Previously, the default select timeout was sys.maxint, but this is a 64-bit value on 64-machines. Now using None when calling select when there is no timeout. Bug reported by (buixor at gmail.com). - Catching EINTR and ignoring it for select, read, write in BaseThread class. - Fixed longopts for pnuke, prsync, pscp, pslurp, pssh (bug reported a Debian user via Andrew Pollock (apollock at debian.org)). Reference: "bug #481901: pssh: options mis-specified" - Added missing environment variables for options for pnuke, prsync, pscp, pslurp, pssh. 2008-06-04 Brent N. Chun * Version 1.3.2 - Added shortopts bug fix from Lev Givon (lev at columbia.edu) in bin/pssh. 2007-04-11 Brent N. Chun * Version 1.3.1 - Reverted I/O back to 1.2.2. style pssh I/O. 2007-04-10 Brent N. Chun * Version 1.3.0 - Added contributions from Deepak Giridharagopal (deepak at brownman.org) * Added ANSI color to pssh, pscp, etc. output. * Each status message now includes a timestamp. * Failures now indicate the cause (e.g., timeout, etc.) * Intermediate directories are created as needed for output. * Removed use of setsid in shell exec. * Using Exception objects rather than raw strings. * Added support for piping stdin to each ssh process. * Added -i option to pssh for "inlining" output to stdout. * Added Python setup.py file for a standard install. - Switched to BSD license. 2006-06-18 Brent N. Chun * Version 1.2.2 - Added patch from Dan Silverstein (dans at pch.net) to fix parsecmdline bug. 2005-12-31 Brent N. Chun * Version 1.2.1 - Changed sys.path so pssh can run without RPM install. - Changed RPM library files to install in /usr/local/lib/python - make install and make uninstall now work as expected for installations from source. 2004-11-10 Brent N. Chun * Added patch from Dave Barr - Adds -a, -z flags to prsync 2004-10-05 Brent N. Chun * Default user is now current user in all programs (on suggestion from Jim Wight ). * Fixed path typo on prsync from 1.1.0 release * Version 1.1.1 2004-10-04 Brent N. Chun * Added patch from Dave Barr - Adds an ssh options flag (-O) to prsync * Added patch from Chad Yoshikawa - Adds a print to stdout flag (-P) to pssh * Version 1.1.0 2004-08-21 Brent N. Chun * All cmds now take -o, -e for stdout, stderr * Checking return values for all cmds * Factored common thread structure out of all cmds * Changed pslurp's dir for local to -L, rather than -o (stdout) * Version 1.0.0 2003-11-20 Brent N. Chun * Added handler for SIGCHLD * Wait for all threads before returning to main thread * Kill all straggler processes when done 2003-11-18 Brent N. Chun * Added pslurp (scp from remote nodes), updated to 0.2.3 2003-11-12 Brent N. Chun * Fixed read bug, so all output is obtained. * Added timeout option (defaults to None for pscp/prsync) * Added verbose option for pssh/pnuke (this is -q or not) * Added environment variables for options * Fixed usage for pnuke 2003-09-06 Brent N. Chun * Added -O for pssh, pscp, and pnuke for passing SSH options * Changed order of options in usage (required, optional) 2003-09-06 Brent N. Chun * Added parallel rsync (prsync) * Added support for "host[:port] user" lines in hosts files * Factored a bit of code out into lib/python/psshutil.py 2003-08-16 Brent N. Chun * Initial version (0.1.0) pssh-2.3.4/INSTALL000066400000000000000000000002701364227332400135330ustar00rootroot00000000000000Installing PSSH =============== This fork of PSSH is supported on Python 3.5 and greater. Install Python and setuptools, and then run: $ python setup.py install Share and enjoy! pssh-2.3.4/README.md000066400000000000000000000011661364227332400137660ustar00rootroot00000000000000PSSH provides parallel versions of OpenSSH and related tools, including pssh, pscp, prsync, pnuke and pslurp. This project includes psshlib which can be used within custom applications. The source code is written in Python. This fork of PSSH is supported on Python 3.5 and later. It was originally written and maintained by Brent N. Chun. Due to his busy schedule, Brent handed over maintenance to Andrew McNabb in October 2009. This project originally located at [Google Code](https://code.google.com/p/parallel-ssh/). Since Google Code has been closed, and has not appeared elsewhere, I (lilydjwg) have exported it to GitHub. pssh-2.3.4/bin/000077500000000000000000000000001364227332400132535ustar00rootroot00000000000000pssh-2.3.4/bin/pnuke000077500000000000000000000053671364227332400143360ustar00rootroot00000000000000#!/usr/bin/env python # -*- Mode: python -*- # Copyright (c) 2009-2012, Andrew McNabb # Copyright (c) 2003-2008, Brent N. Chun """Nukes all processes that match pattern running as user on the set of nodes in hosts.txt. """ import os import sys parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0]))) if os.path.exists(os.path.join(parent, 'psshlib')): sys.path.insert(0, parent) from psshlib import psshutil from psshlib.task import Task from psshlib.manager import Manager, FatalError from psshlib.cli import common_parser, common_defaults _DEFAULT_TIMEOUT = 60 def option_parser(): parser = common_parser() parser.usage = "%prog [OPTIONS] pattern" parser.epilog = "Example: pnuke -h hosts.txt -l irb2 java" return parser def parse_args(): parser = option_parser() defaults = common_defaults(timeout=_DEFAULT_TIMEOUT) parser.set_defaults(**defaults) opts, args = parser.parse_args() if len(args) < 1: parser.error('Pattern not specified.') if len(args) > 1: parser.error('Extra arguments given after the pattern.') if not opts.host_files and not opts.host_strings: parser.error('Hosts not specified.') return opts, args def do_pnuke(hosts, pattern, opts): if opts.outdir and not os.path.exists(opts.outdir): os.makedirs(opts.outdir) if opts.errdir and not os.path.exists(opts.errdir): os.makedirs(opts.errdir) manager = Manager(opts) for host, port, user in hosts: cmd = ['ssh', host, '-o', 'NumberOfPasswordPrompts=1'] if opts.options: for opt in opts.options: cmd += ['-o', opt] if user: cmd += ['-l', user] if port: cmd += ['-p', port] if opts.extra: cmd.extend(opts.extra) cmd.append('pkill -9 %s' % pattern) t = Task(host, port, user, cmd, opts) manager.add_task(t) try: statuses = manager.run() except FatalError: sys.exit(1) if statuses and min(statuses) < 0: # At least one process was killed. sys.exit(3) for status in statuses: if status == 255: sys.exit(4) for status in statuses: if status != 0: sys.exit(5) if __name__ == "__main__": opts, args = parse_args() pattern = args[0] try: hosts = psshutil.read_host_files(opts.host_files, opts.host_glob, default_user=opts.user) except IOError: _, e, _ = sys.exc_info() sys.stderr.write('Could not open hosts file: %s\n' % e.strerror) sys.exit(1) if opts.host_strings: for s in opts.host_strings: hosts.extend(psshutil.parse_host_string(s, default_user=opts.user)) do_pnuke(hosts, pattern, opts) pssh-2.3.4/bin/prsync000077500000000000000000000072171364227332400145260ustar00rootroot00000000000000#!/usr/bin/env python # -*- Mode: python -*- # Copyright (c) 2009-2012, Andrew McNabb # Copyright (c) 2003-2008, Brent N. Chun """Parallel rsync to the set of nodes in hosts.txt. For each node, we essentially do a rsync -rv -e ssh local user@host:remote. Note that remote must be an absolute path. """ import os import sys parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0]))) if os.path.exists(os.path.join(parent, 'psshlib')): sys.path.insert(0, parent) from psshlib import psshutil from psshlib.task import Task from psshlib.manager import Manager, FatalError from psshlib.cli import common_parser, common_defaults def option_parser(): parser = common_parser() parser.usage = "%prog [OPTIONS] local remote" parser.epilog = ("Example: prsync -r -h hosts.txt -l irb2 foo " + "/home/irb2/foo") parser.add_option('-r', '--recursive', dest='recursive', action='store_true', help='recusively copy directories (OPTIONAL)') parser.add_option('-a', '--archive', dest='archive', action='store_true', help='use rsync -a (archive mode) (OPTIONAL)') parser.add_option('-z', '--compress', dest='compress', action='store_true', help='use rsync compression (OPTIONAL)') parser.add_option('-S', '--ssh-args', metavar="ARGS", dest='ssh_args', action='store', help='extra arguments for ssh') return parser def parse_args(): parser = option_parser() defaults = common_defaults() parser.set_defaults(**defaults) opts, args = parser.parse_args() if len(args) < 1: parser.error('Paths not specified.') if len(args) < 2: parser.error('Remote path not specified.') if not opts.host_files and not opts.host_strings: parser.error('Hosts not specified.') return opts, args def do_prsync(hosts, local, remote, opts): if opts.outdir and not os.path.exists(opts.outdir): os.makedirs(opts.outdir) if opts.errdir and not os.path.exists(opts.errdir): os.makedirs(opts.errdir) manager = Manager(opts) for host, port, user in hosts: ssh = ['ssh'] if opts.options: for opt in opts.options: ssh += ['-o', opt] if port: ssh += ['-p', port] if opts.ssh_args: ssh += [opts.ssh_args] cmd = ['rsync', '-e', ' '.join(ssh)] if opts.verbose: cmd.append('-v') if opts.recursive: cmd.append('-r') if opts.archive: cmd.append('-a') if opts.compress: cmd.append('-z') if opts.extra: cmd.extend(opts.extra) cmd.extend(local) if user: cmd.append('%s@%s:%s' % (user, host, remote)) else: cmd.append('%s:%s' % (host, remote)) t = Task(host, port, user, cmd, opts) manager.add_task(t) try: statuses = manager.run() except FatalError: sys.exit(1) if statuses and min(statuses) < 0: # At least one process was killed. sys.exit(3) for status in statuses: if status != 0: sys.exit(4) if __name__ == "__main__": opts, args = parse_args() local = args[0:-1] remote = args[-1] try: hosts = psshutil.read_host_files(opts.host_files, opts.host_glob, default_user=opts.user) except IOError: _, e, _ = sys.exc_info() sys.stderr.write('Could not open hosts file: %s\n' % e.strerror) sys.exit(1) if opts.host_strings: for s in opts.host_strings: hosts.extend(psshutil.parse_host_string(s, default_user=opts.user)) do_prsync(hosts, local, remote, opts) pssh-2.3.4/bin/pscp000077500000000000000000000061001364227332400141430ustar00rootroot00000000000000#!/usr/bin/env python # -*- Mode: python -*- # Copyright (c) 2009-2012, Andrew McNabb # Copyright (c) 2003-2008, Brent N. Chun """Parallel scp to the set of nodes in hosts.txt. For each node, we essentially do a scp [-r] local user@host:remote. This program also uses the -q (quiet) and -C (compression) options. Note that remote must be an absolute path. """ import os import sys parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0]))) if os.path.exists(os.path.join(parent, 'psshlib')): sys.path.insert(0, parent) from psshlib import psshutil from psshlib.task import Task from psshlib.manager import Manager, FatalError from psshlib.cli import common_parser, common_defaults def option_parser(): parser = common_parser() parser.usage = "%prog [OPTIONS] local remote" parser.epilog = ("Example: pscp -h hosts.txt -l irb2 foo.txt " + "/home/irb2/foo.txt") parser.add_option('-r', '--recursive', dest='recursive', action='store_true', help='recusively copy directories (OPTIONAL)') return parser def parse_args(): parser = option_parser() defaults = common_defaults() parser.set_defaults(**defaults) opts, args = parser.parse_args() if len(args) < 1: parser.error('Paths not specified.') if len(args) < 2: parser.error('Remote path not specified.') if not opts.host_files and not opts.host_strings: parser.error('Hosts not specified.') return opts, args def do_pscp(hosts, localargs, remote, opts): if opts.outdir and not os.path.exists(opts.outdir): os.makedirs(opts.outdir) if opts.errdir and not os.path.exists(opts.errdir): os.makedirs(opts.errdir) manager = Manager(opts) for host, port, user in hosts: cmd = ['scp', '-qC'] if opts.options: for opt in opts.options: cmd += ['-o', opt] if port: cmd += ['-P', port] if opts.recursive: cmd.append('-r') if opts.extra: cmd.extend(opts.extra) cmd.extend(localargs) if user: cmd.append('%s@%s:%s' % (user, host, remote)) else: cmd.append('%s:%s' % (host, remote)) t = Task(host, port, user, cmd, opts) manager.add_task(t) try: statuses = manager.run() except FatalError: sys.exit(1) if statuses and min(statuses) < 0: # At least one process was killed. sys.exit(3) for status in statuses: if status != 0: sys.exit(4) if __name__ == "__main__": opts, args = parse_args() localargs = args[0:-1] remote = args[-1] try: hosts = psshutil.read_host_files(opts.host_files, opts.host_glob, default_user=opts.user) except IOError: _, e, _ = sys.exc_info() sys.stderr.write('Could not open hosts file: %s\n' % e.strerror) sys.exit(1) if opts.host_strings: for s in opts.host_strings: hosts.extend(psshutil.parse_host_string(s, default_user=opts.user)) do_pscp(hosts, localargs, remote, opts) pssh-2.3.4/bin/pslurp000077500000000000000000000075311364227332400145340ustar00rootroot00000000000000#!/usr/bin/env python # -*- Mode: python -*- # Copyright (c) 2009-2012, Andrew McNabb # Copyright (c) 2003-2008, Brent N. Chun """Parallel scp from the set of nodes in hosts.txt. For each node, we essentially do a scp [-r] user@host:remote outdir//local. This program also uses the -q (quiet) and -C (compression) options. """ import os import sys parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0]))) if os.path.exists(os.path.join(parent, 'psshlib')): sys.path.insert(0, parent) from psshlib import psshutil from psshlib.task import Task from psshlib.manager import Manager, FatalError from psshlib.cli import common_parser, common_defaults def option_parser(): parser = common_parser() parser.usage = "%prog [OPTIONS] remote local" parser.epilog = ("Example: pslurp -h hosts.txt -L /tmp/outdir -l irb2 " + " /home/irb2/foo.txt foo.txt") parser.add_option('-r', '--recursive', dest='recursive', action='store_true', help='recusively copy directories (OPTIONAL)') parser.add_option('-L', '--localdir', dest='localdir', help='output directory for remote file copies') return parser def parse_args(): parser = option_parser() defaults = common_defaults() parser.set_defaults(**defaults) opts, args = parser.parse_args() if len(args) < 1: parser.error('Paths not specified.') if len(args) < 2: parser.error('Local path not specified.') if len(args) > 2: parser.error('Extra arguments given after the local path.') if not opts.host_files and not opts.host_strings: parser.error('Hosts not specified.') return opts, args def do_pslurp(hosts, remote, local, opts): if opts.localdir and not os.path.exists(opts.localdir): os.makedirs(opts.localdir) if opts.outdir and not os.path.exists(opts.outdir): os.makedirs(opts.outdir) if opts.errdir and not os.path.exists(opts.errdir): os.makedirs(opts.errdir) for host, port, user in hosts: if opts.localdir: dirname = "%s/%s:%s" % (opts.localdir, host, port) else: dirname = '%s:%s' % (host, port) if not os.path.exists(dirname): os.mkdir(dirname) manager = Manager(opts) for host, port, user in hosts: if opts.localdir: localpath = "%s/%s:%s/%s" % (opts.localdir, host, port, local) else: localpath = "%s:%s/%s" % (host, port, local) cmd = ['scp', '-qC'] if opts.options: for opt in opts.options: cmd += ['-o', opt] if port: cmd += ['-P', port] if opts.recursive: cmd.append('-r') if opts.extra: cmd.extend(opts.extra) if user: cmd.append('%s@%s:%s' % (user, host, remote)) else: cmd.append('%s:%s' % (host, remote)) cmd.append(localpath) t = Task(host, port, user, cmd, opts) manager.add_task(t) try: statuses = manager.run() except FatalError: sys.exit(1) if statuses and min(statuses) < 0: # At least one process was killed. sys.exit(3) for status in statuses: if status == 255: sys.exit(4) for status in statuses: if status != 0: sys.exit(5) if __name__ == "__main__": opts, args = parse_args() remote = args[0] local = args[1] try: hosts = psshutil.read_host_files(opts.host_files, opts.host_glob, default_user=opts.user) except IOError: _, e, _ = sys.exc_info() sys.stderr.write('Could not open hosts file: %s\n' % e.strerror) sys.exit(1) if opts.host_strings: for s in opts.host_strings: hosts.extend(psshutil.parse_host_string(s, default_user=opts.user)) do_pslurp(hosts, remote, local, opts) pssh-2.3.4/bin/pssh000077500000000000000000000074641364227332400141710ustar00rootroot00000000000000#!/usr/bin/env python # -*- Mode: python -*- # Copyright (c) 2009-2012, Andrew McNabb # Copyright (c) 2003-2008, Brent N. Chun """Parallel ssh to the set of nodes in hosts.txt. For each node, this essentially does an "ssh host -l user prog [arg0] [arg1] ...". The -o option can be used to store stdout from each remote node in a directory. Each output file in that directory will be named by the corresponding remote node's hostname or IP address. """ import os import sys parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0]))) if os.path.exists(os.path.join(parent, 'psshlib')): sys.path.insert(0, parent) from psshlib import psshutil from psshlib.manager import Manager, FatalError from psshlib.task import Task from psshlib.cli import common_parser, common_defaults _DEFAULT_TIMEOUT = 60 def option_parser(): parser = common_parser() parser.usage = "%prog [OPTIONS] command [...]" parser.epilog = "Example: pssh -h hosts.txt -l irb2 -o /tmp/foo uptime" parser.add_option('-i', '--inline', dest='inline', action='store_true', help='inline aggregated output and error for each server') parser.add_option('--inline-stdout', dest='inline_stdout', action='store_true', help='inline standard output for each server') parser.add_option('-I', '--send-input', dest='send_input', action='store_true', help='read from standard input and send as input to ssh') parser.add_option('-P', '--print', dest='print_out', action='store_true', help='print output as we get it') return parser def parse_args(): parser = option_parser() defaults = common_defaults(timeout=_DEFAULT_TIMEOUT) parser.set_defaults(**defaults) opts, args = parser.parse_args() if len(args) == 0 and not opts.send_input: parser.error('Command not specified.') if not opts.host_files and not opts.host_strings: parser.error('Hosts not specified.') return opts, args def do_pssh(hosts, cmdline, opts): if opts.outdir and not os.path.exists(opts.outdir): os.makedirs(opts.outdir) if opts.errdir and not os.path.exists(opts.errdir): os.makedirs(opts.errdir) if opts.send_input: if hasattr(sys.stdin, 'buffer'): stdin = sys.stdin.buffer.read() else: stdin = sys.stdin.read() else: stdin = None manager = Manager(opts) for host, port, user in hosts: cmd = ['ssh', '-T', host, '-o', 'NumberOfPasswordPrompts=1', '-o', 'SendEnv=PSSH_NODENUM', '-o', 'SendEnv=PSSH_NUMNODES', '-o', 'SendEnv=PSSH_HOST'] if opts.options: for opt in opts.options: cmd += ['-o', opt] if user: cmd += ['-l', user] if port: cmd += ['-p', port] if opts.extra: cmd.extend(opts.extra) if cmdline: cmd.append(cmdline) t = Task(host, port, user, cmd, opts, stdin) manager.add_task(t) try: statuses = manager.run() except FatalError: sys.exit(1) if any(x < 0 for x in statuses if x): # At least one process was killed. sys.exit(3) if any(x == 255 for x in statuses): sys.exit(4) if any(x != 0 for x in statuses): sys.exit(5) if __name__ == "__main__": opts, args = parse_args() cmdline = " ".join(args) try: hosts = psshutil.read_host_files(opts.host_files, opts.host_glob, default_user=opts.user) except IOError: _, e, _ = sys.exc_info() sys.stderr.write('Could not open hosts file: %s\n' % e.strerror) sys.exit(1) if opts.host_strings: for s in opts.host_strings: hosts.extend(psshutil.parse_host_string(s, default_user=opts.user)) do_pssh(hosts, cmdline, opts) pssh-2.3.4/bin/pssh-askpass000077500000000000000000000004161364227332400156220ustar00rootroot00000000000000#!/usr/bin/env python import os import sys parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0]))) if os.path.exists(os.path.join(parent, 'psshlib')): sys.path.insert(0, parent) from psshlib.askpass_client import askpass_main askpass_main() pssh-2.3.4/doc/000077500000000000000000000000001364227332400132505ustar00rootroot00000000000000pssh-2.3.4/doc/index.html000066400000000000000000000225521364227332400152530ustar00rootroot00000000000000pssh HOWTO

pssh HOWTO

0.1, 2003-11-13

Revision History
Revision 0.12003-11-13
Initial version.

1. Installation and Setup

To install the software, become root on your machine and do the following (on RedHat systems):

   # rpm -ivh pssh-0.2.3-1.i386.rpm
   Preparing...                ########################################### [100%]
      1:pssh                   ########################################### [100%]

By default, the software installs itself in /usr/localbin and /usr/local/lib. Thus, you'll next want to modify your PATH if needed:

# export PATH=$PATH:/usr/local/bin

2. Preliminaries

All four programs will print their usage and give an example if no arguments are given. For example, with pssh:

   # pssh
   Usage: pssh [OPTIONS] -h hosts.txt prog [arg0] ..
   
     -h --hosts   hosts file (each line "host[:port] [user]")
     -l --user    username (OPTIONAL)
     -p --par     max number of parallel threads (OPTIONAL)
     -o --outdir  output directory for stdout files (OPTIONAL)
     -t --timeout timeout in seconds to do ssh to a host (OPTIONAL)
     -v --verbose turn on warning and diagnostic messages (OPTIONAL)
     -O --options SSH options (OPTIONAL)
   
   Example: pssh -h ips.txt -l irb2 -o /tmp/foo uptime

And for pscp:

   # pscp
   Usage: pscp [OPTIONS] -h hosts.txt local remote
   
     -h --hosts     hosts file (each line "host[:port] [login]")
     -r --recursive recusively copy directories (OPTIONAL)
     -l --user      username (OPTIONAL)
     -p --par       max number of parallel threads (OPTIONAL)
     -t --timeout   timeout in seconds to do scp to a host (OPTIONAL)
     -O --options   SSH options (OPTIONAL)
   
   Example: pscp -h hosts.txt -l irb2 foo.txt /home/irb2/foo.txt

Note that before using any of these tools, you will need to start ssh-agent! This can be done as follows (substitute zsh with your particular shell).

   # ssh-agent zsh
   # ssh-add
   Enter passphrase for /x/bnc/.ssh/identity: 

3. Examples


3.2. pscp

Here's an example of using pscp to copy files in parallel to a set of machines.

   # pscp -h ips.txt -l irb2 /etc/hosts /tmp/hosts
   Success on 128.112.152.122:22
   Success on 18.31.0.190:22
   Success on 128.232.103.201:22

Using the -r option will perform a recursive copy for copying entire directories.


4. Environment Variables

All four programs take similar sets of options. All of these options can be set using the following environment variables:

   PSSH_HOSTS
   PSSH_USER
   PSSH_PAR
   PSSH_OUTDIR
   PSSH_VERBOSE
   PSSH_OPTIONS

Here are some example settings:

   # export PSSH_HOSTS="/x/bnc/ips.txt"
   # export PSSH_USER="irb2"
   # export PSSH_PAR="32"
   # export PSSH_OUTDIR="/tmp/bar"
   # export PSSH_VERBOSE="0"
   # export PSSH_OPTIONS="UserKnownHostsFile /tmp/known_hosts"

Using the above settings, the examples can be executed succinctly as:

   # pssh hostname
   Success on 128.112.152.122:22
   Success on 18.31.0.190:22
   Success on 128.232.103.201:22
   
   # ls /tmp/bar 
   128.112.152.122  128.232.103.201  18.31.0.190
   
   # cat /tmp/bar/*
   planetlab-1.cs.princeton.edu
   planetlab1.xeno.cl.cam.ac.uk
   planetlab1.lcs.mit.edu
   
   # pscp /etc/hosts /tmp/hosts
   Success on 128.112.152.122:22
   Success on 18.31.0.190:22
   Success on 128.232.103.201:22
   
   # pnuke java   
   Success on 128.112.152.122:22
   Success on 18.31.0.190:22
   Success on 128.232.103.201:22

5. Feedback

Send me email if you're having problems, find bugs, or have any random comments: Brent Chun (bnc at theether.org). Thus far, I've primarily been testing this software on PlanetLab.

pssh-2.3.4/doc/pssh-HOWTO.html000066400000000000000000000225521364227332400160170ustar00rootroot00000000000000pssh HOWTO

pssh HOWTO

0.1, 2003-11-13

Revision History
Revision 0.12003-11-13
Initial version.

1. Installation and Setup

To install the software, become root on your machine and do the following (on RedHat systems):

   # rpm -ivh pssh-0.2.3-1.i386.rpm
   Preparing...                ########################################### [100%]
      1:pssh                   ########################################### [100%]

By default, the software installs itself in /usr/localbin and /usr/local/lib. Thus, you'll next want to modify your PATH if needed:

# export PATH=$PATH:/usr/local/bin

2. Preliminaries

All four programs will print their usage and give an example if no arguments are given. For example, with pssh:

   # pssh
   Usage: pssh [OPTIONS] -h hosts.txt prog [arg0] ..
   
     -h --hosts   hosts file (each line "host[:port] [user]")
     -l --user    username (OPTIONAL)
     -p --par     max number of parallel threads (OPTIONAL)
     -o --outdir  output directory for stdout files (OPTIONAL)
     -t --timeout timeout in seconds to do ssh to a host (OPTIONAL)
     -v --verbose turn on warning and diagnostic messages (OPTIONAL)
     -O --options SSH options (OPTIONAL)
   
   Example: pssh -h ips.txt -l irb2 -o /tmp/foo uptime

And for pscp:

   # pscp
   Usage: pscp [OPTIONS] -h hosts.txt local remote
   
     -h --hosts     hosts file (each line "host[:port] [login]")
     -r --recursive recusively copy directories (OPTIONAL)
     -l --user      username (OPTIONAL)
     -p --par       max number of parallel threads (OPTIONAL)
     -t --timeout   timeout in seconds to do scp to a host (OPTIONAL)
     -O --options   SSH options (OPTIONAL)
   
   Example: pscp -h hosts.txt -l irb2 foo.txt /home/irb2/foo.txt

Note that before using any of these tools, you will need to start ssh-agent! This can be done as follows (substitute zsh with your particular shell).

   # ssh-agent zsh
   # ssh-add
   Enter passphrase for /x/bnc/.ssh/identity: 

3. Examples


3.2. pscp

Here's an example of using pscp to copy files in parallel to a set of machines.

   # pscp -h ips.txt -l irb2 /etc/hosts /tmp/hosts
   Success on 128.112.152.122:22
   Success on 18.31.0.190:22
   Success on 128.232.103.201:22

Using the -r option will perform a recursive copy for copying entire directories.


4. Environment Variables

All four programs take similar sets of options. All of these options can be set using the following environment variables:

   PSSH_HOSTS
   PSSH_USER
   PSSH_PAR
   PSSH_OUTDIR
   PSSH_VERBOSE
   PSSH_OPTIONS

Here are some example settings:

   # export PSSH_HOSTS="/x/bnc/ips.txt"
   # export PSSH_USER="irb2"
   # export PSSH_PAR="32"
   # export PSSH_OUTDIR="/tmp/bar"
   # export PSSH_VERBOSE="0"
   # export PSSH_OPTIONS="UserKnownHostsFile /tmp/known_hosts"

Using the above settings, the examples can be executed succinctly as:

   # pssh hostname
   Success on 128.112.152.122:22
   Success on 18.31.0.190:22
   Success on 128.232.103.201:22
   
   # ls /tmp/bar 
   128.112.152.122  128.232.103.201  18.31.0.190
   
   # cat /tmp/bar/*
   planetlab-1.cs.princeton.edu
   planetlab1.xeno.cl.cam.ac.uk
   planetlab1.lcs.mit.edu
   
   # pscp /etc/hosts /tmp/hosts
   Success on 128.112.152.122:22
   Success on 18.31.0.190:22
   Success on 128.232.103.201:22
   
   # pnuke java   
   Success on 128.112.152.122:22
   Success on 18.31.0.190:22
   Success on 128.232.103.201:22

5. Feedback

Send me email if you're having problems, find bugs, or have any random comments: Brent Chun (bnc at theether.org). Thus far, I've primarily been testing this software on PlanetLab.

pssh-2.3.4/doc/pssh-HOWTO.pdf000066400000000000000000000543201364227332400156220ustar00rootroot00000000000000%PDF-1.3 1 0 obj << /S /GoTo /D (1.0) >> endobj 4 0 obj (Table of Contents) endobj 5 0 obj << /S /GoTo /D (1.1.1) >> endobj 8 0 obj (1. Installation and Setup) endobj 9 0 obj << /S /GoTo /D (1.2.1) >> endobj 12 0 obj (2. Preliminaries) endobj 13 0 obj << /S /GoTo /D (1.3.1) >> endobj 16 0 obj (3. Examples) endobj 17 0 obj << /S /GoTo /D (1.3.1.2) >> endobj 20 0 obj (3.1. pssh) endobj 21 0 obj << /S /GoTo /D (1.3.2.2) >> endobj 24 0 obj (3.2. pscp) endobj 25 0 obj << /S /GoTo /D (1.3.3.2) >> endobj 28 0 obj (3.3. pnuke) endobj 29 0 obj << /S /GoTo /D (1.4.1) >> endobj 32 0 obj (4. Environment Variables) endobj 33 0 obj << /S /GoTo /D (1.5.1) >> endobj 36 0 obj (5. Feedback) endobj 37 0 obj << /S /GoTo /D [38 0 R /Fit ] >> endobj 40 0 obj << /Length 1007 /Filter /FlateDecode >> stream xKOW=˙s>TM*jUbM՟6B [wXGYGM M?]jtq}G;e]EiAV9o'߼͋Q^o/Kn˫4owi%2Kޥ,Mc^QЭ7/B,7KMo%'] Yo&6K&i̒tnb\/>9kU'Uh1tF]cL =r5'brvZʐ}lg|oy(>olBCCCCCCCCC444444444444JCCCCCCCCCCC56+a|2tLCb4Vf/t6g׳n6=HM(frr9иhi+ ȿ~J5Rb=kr};?V1Ms ͧ^W444444444444JCCCCCCCCCCCECCCCCCCCCCCښϟk.MCK6.WՊ*IJ=h ~/yՃh+  |GsC1U9@c؈h+ иhi+ ƀ'ƀCdzP2-kCU) LC444444444444.Z4444444444444JCCCCCCCCCCg::>[mb.<{H,sv6Y\O/i'|>]&fm(X6zנzwԫF[ihhhhhhhhhhhqVmڣճeV,&= bendstream endobj 38 0 obj << /Type /Page /Contents 40 0 R /Resources 39 0 R /MediaBox [0 0 609.714 789.041] /Parent 66 0 R /Annots [ 46 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R 54 0 R 57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R ] >> endobj 46 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [71.731 552.418 175.81 561.305] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 49 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [533.001 552.418 537.983 561.305] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 50 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [71.731 538.979 139.068 545.962] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 51 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [533.001 538.979 537.983 545.962] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 52 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [71.731 521.733 123.208 530.62] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 53 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [533.001 521.733 537.983 530.62] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 54 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [95.641 506.257 130.789 515.168] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 57 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [533.001 506.257 537.983 515.168] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 58 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [95.641 493.305 131.337 502.216] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 59 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [533.001 493.305 537.983 502.216] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 60 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [95.641 480.354 137.325 489.265] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 61 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [533.001 480.354 537.983 489.265] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 62 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [71.731 467.049 180.104 474.032] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 63 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [533.001 467.049 537.983 474.032] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 64 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [71.731 451.706 122.401 458.69] /Subtype /Link /A << /S /GoTo /D (79) >> >> endobj 65 0 obj << /Type /Annot /Border [0 0 0] /H /I /C [1 0 0] /Rect [533.001 451.706 537.983 458.69] /Subtype /Link /A << /S /GoTo /D (79) >> >> endobj 41 0 obj << /D [38 0 R /XYZ 71.731 729.265 null] >> endobj 42 0 obj << /D [38 0 R /XYZ 71.731 718.306 null] >> endobj 43 0 obj << /D [38 0 R /XYZ 71.731 718.306 null] >> endobj 2 0 obj << /D [38 0 R /XYZ 215.565 576 null] >> endobj 39 0 obj << /Font << /F23 45 0 R /F25 48 0 R /F26 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 77 0 obj << /Length 1507 /Filter /FlateDecode >> stream xڭX]o6}ϯ )Y!ڵAh[$ "1)R^{x): ?)GR’d]]-~E8I1h ng,9W'MhL8,7z2(lReeBIVqULD2IIDg!lqE xaz2!F=Mie-6V|-ԫAd?FB =`1 Nn^tiUzWֺY 4rqF΁[p:ȿx9Sv{x%a iEOh={?0ڦ2 xܙV# #OI-7,([d-G,MB|A4 yhBh|bޠK/?1r,?bSFR0>mLF++9 "ܸ*%!< :XgM>vs g4#pd1OhAYFf$ ;N^dJg޳Ywm{”ɋ^5!!$Oa_!ѐ΁㐭ۆEb|9d1Fʴo?ߛC;v2qJ /!|Y n~nz1hZmRp3H)8Evv'pl G P?d~Mв)Eِe.mWZIakːOSx_;nz&z:dFGCQrg7n߾/|{gvB*IԳƾN M(k0pf`SQP9W[dxI>CaY_:8 "Kx[gڔYAi HԏOgAY Zǭj,սh:.IѩMwlrZ|D(R%a =QO[k-JYss d]ͣ摷+!- TZDm\zZȶ5+֦_qd7lahIJo})HG tyR4RW}9&'v_U5F^`Fqsi$f *QA͸.Wd)Jf#X+M&ek3wJzsb(ml2Kp4_Ec٧iCvendstream endobj 76 0 obj << /Type /Page /Contents 77 0 R /Resources 75 0 R /MediaBox [0 0 609.714 789.041] /Parent 66 0 R >> endobj 78 0 obj << /D [76 0 R /XYZ 71.731 729.265 null] >> endobj 67 0 obj << /D [76 0 R /XYZ 71.731 718.306 null] >> endobj 6 0 obj << /D [76 0 R /XYZ 236.753 707.841 null] >> endobj 79 0 obj << /D [76 0 R /XYZ 71.731 697.698 null] >> endobj 80 0 obj << /D [76 0 R /XYZ 198.664 687.716 null] >> endobj 83 0 obj << /D [76 0 R /XYZ 71.731 675.597 null] >> endobj 84 0 obj << /D [76 0 R /XYZ 71.731 631.414 null] >> endobj 85 0 obj << /D [76 0 R /XYZ 233.133 619.871 null] >> endobj 86 0 obj << /D [76 0 R /XYZ 322.438 619.871 null] >> endobj 87 0 obj << /D [76 0 R /XYZ 92.483 606.919 null] >> endobj 88 0 obj << /D [76 0 R /XYZ 71.731 594.8 null] >> endobj 68 0 obj << /D [76 0 R /XYZ 71.731 573.93 null] >> endobj 10 0 obj << /D [76 0 R /XYZ 177.791 535.965 null] >> endobj 89 0 obj << /D [76 0 R /XYZ 71.731 528.613 null] >> endobj 90 0 obj << /D [76 0 R /XYZ 496.694 515.841 null] >> endobj 91 0 obj << /D [76 0 R /XYZ 71.731 503.721 null] >> endobj 92 0 obj << /D [76 0 R /XYZ 71.731 354.632 null] >> endobj 93 0 obj << /D [76 0 R /XYZ 105.484 343.089 null] >> endobj 94 0 obj << /D [76 0 R /XYZ 71.731 331.718 null] >> endobj 95 0 obj << /D [76 0 R /XYZ 71.731 193.537 null] >> endobj 96 0 obj << /D [76 0 R /XYZ 255.311 181.993 null] >> endobj 99 0 obj << /D [76 0 R /XYZ 71.731 169.041 null] >> endobj 100 0 obj << /D [76 0 R /XYZ 71.731 156.922 null] >> endobj 69 0 obj << /D [76 0 R /XYZ 71.731 112.74 null] >> endobj 75 0 obj << /Font << /F23 45 0 R /F26 56 0 R /F32 82 0 R /F33 98 0 R >> /ProcSet [ /PDF /Text ] >> endobj 103 0 obj << /Length 1511 /Filter /FlateDecode >> stream xڥXKs6SLe;AF䘙iMg05 1b{Z>fnd22YTsk1NZqX2ȩޕUppP}o/bO)|)OǞU("'YaitG# #SC42>@inA1L}(2g!k%$A6%7D甘~+E47> \ئńfPZ)e>QT?xS)UPlQ(B\D'1F1"$&ۢS~ Qp5/dOͯ3sE,Gvmn.o4Q:> Q쇨ϼ}9]PJTLyNZ+ }[r6MQ5~mM#v/`@UbQ*+4]fiAKL_>l_ݣ#;qs;Y7MB7.<.MCwrҩO11.~P 0w}9mZ3(=p䋜ЈF4ucU(:ԢM׋a*z1񘥋(zǁ`1C=hue;8xQ7i:&=;Uj<[~c ykGJ8`#kA}FƬb1,Ltieq+Chx(B[cXۗևÛ" m0[0#U<epQ-tWWPg (Z{yEZה#6v/N 9V?0>j-cFw˾H>)g&1EID @ZةrBh[%0qpx+|} SعA6 CbSż&[_5Mls5"!K0URRl%n! J"A.8 e0Vywߴ&_=NzlW06rm,ƧƮ#|&14.Q˞KSo}c\|~xN}L2#5yoZn!^f-}7Zg ]lc=5ޘ ܓ2sbd~ ߊױMᣎR8s.5\% ᅵ$m|aSN%hOydgUb b/8 {_&؝xc]"hJO̭(,,ƨhkҪfynb3j;L_@M;(FDK23<_M5endstream endobj 102 0 obj << /Type /Page /Contents 103 0 R /Resources 101 0 R /MediaBox [0 0 609.714 789.041] /Parent 66 0 R >> endobj 104 0 obj << /D [102 0 R /XYZ 71.731 729.265 null] >> endobj 14 0 obj << /D [102 0 R /XYZ 154.665 708.149 null] >> endobj 70 0 obj << /D [102 0 R /XYZ 71.731 705.18 null] >> endobj 18 0 obj << /D [102 0 R /XYZ 122.898 673.679 null] >> endobj 105 0 obj << /D [102 0 R /XYZ 71.731 665.226 null] >> endobj 106 0 obj << /D [102 0 R /XYZ 186.44 654.75 null] >> endobj 107 0 obj << /D [102 0 R /XYZ 462.183 654.75 null] >> endobj 108 0 obj << /D [102 0 R /XYZ 94.705 641.798 null] >> endobj 109 0 obj << /D [102 0 R /XYZ 212.173 641.798 null] >> endobj 110 0 obj << /D [102 0 R /XYZ 71.731 629.679 null] >> endobj 111 0 obj << /D [102 0 R /XYZ 71.731 422.308 null] >> endobj 112 0 obj << /D [102 0 R /XYZ 118.396 410.765 null] >> endobj 113 0 obj << /D [102 0 R /XYZ 372.54 384.862 null] >> endobj 114 0 obj << /D [102 0 R /XYZ 111.023 371.91 null] >> endobj 115 0 obj << /D [102 0 R /XYZ 151.91 371.91 null] >> endobj 116 0 obj << /D [102 0 R /XYZ 332.481 371.91 null] >> endobj 117 0 obj << /D [102 0 R /XYZ 373.368 371.91 null] >> endobj 71 0 obj << /D [102 0 R /XYZ 71.731 351.821 null] >> endobj 22 0 obj << /D [102 0 R /XYZ 122.898 318.51 null] >> endobj 118 0 obj << /D [102 0 R /XYZ 71.731 310.058 null] >> endobj 119 0 obj << /D [102 0 R /XYZ 183.083 299.581 null] >> endobj 120 0 obj << /D [102 0 R /XYZ 71.731 287.462 null] >> endobj 121 0 obj << /D [102 0 R /XYZ 71.731 232.843 null] >> endobj 72 0 obj << /D [102 0 R /XYZ 71.731 212.941 null] >> endobj 26 0 obj << /D [102 0 R /XYZ 130.083 179.631 null] >> endobj 122 0 obj << /D [102 0 R /XYZ 71.731 171.179 null] >> endobj 123 0 obj << /D [102 0 R /XYZ 89.714 160.702 null] >> endobj 124 0 obj << /D [102 0 R /XYZ 195.397 147.751 null] >> endobj 125 0 obj << /D [102 0 R /XYZ 148.373 134.799 null] >> endobj 126 0 obj << /D [102 0 R /XYZ 71.731 122.68 null] >> endobj 101 0 obj << /Font << /F33 98 0 R /F23 45 0 R /F26 56 0 R /F32 82 0 R >> /ProcSet [ /PDF /Text ] >> endobj 129 0 obj << /Length 1013 /Filter /FlateDecode >> stream xڽW[o6~ϯihnbJ:Q-K(7oX6b X΅2 +D mo($ A,Q(ޥ7[ϳb^]s؇b?RE;p3O{>1!;|<@ `첌qvU'l7C WKam =!2[bvQ#b#OL0+ZvB)FOdu4@a`BEOƧ'$C3rQ7 \]}(4f5 &"O/Bmz: .5,z.o[c!*>iOVWM{)ujc@DBxDs#,WTKD0CDxy#-+[-" MNWv)8T> endobj 130 0 obj << /D [128 0 R /XYZ 71.731 729.265 null] >> endobj 131 0 obj << /D [128 0 R /XYZ 71.731 686.537 null] >> endobj 132 0 obj << /D [128 0 R /XYZ 205.907 673.773 null] >> endobj 133 0 obj << /D [128 0 R /XYZ 350.673 673.773 null] >> endobj 134 0 obj << /D [128 0 R /XYZ 119.87 660.822 null] >> endobj 73 0 obj << /D [128 0 R /XYZ 71.731 643.721 null] >> endobj 30 0 obj << /D [128 0 R /XYZ 241.287 606.506 null] >> endobj 135 0 obj << /D [128 0 R /XYZ 71.731 599.153 null] >> endobj 136 0 obj << /D [128 0 R /XYZ 71.731 563.367 null] >> endobj 137 0 obj << /D [128 0 R /XYZ 71.731 482.518 null] >> endobj 138 0 obj << /D [128 0 R /XYZ 71.731 458.496 null] >> endobj 139 0 obj << /D [128 0 R /XYZ 71.731 379.345 null] >> endobj 140 0 obj << /D [128 0 R /XYZ 71.731 355.681 null] >> endobj 127 0 obj << /Font << /F33 98 0 R /F32 82 0 R /F26 56 0 R /F23 45 0 R >> /ProcSet [ /PDF /Text ] >> endobj 143 0 obj << /Length 434 /Filter /FlateDecode >> stream x}RM0WV[*_=UJCw8 iC Qu+߼7  E&\ZCJO>`FhDL7fܧR$U$ݟp톡d4~yb2{M>gBy5΄K#I$سT4W^>:˳-$n/{ ]qauMV!a}k& )O"lu}׮>EP,GmEЙ6S> m.=&>?Y\ ^EQcw^Gf c=3`? үl p!D{}ϴɯ4UU=˝d5&v??̻{_w'xT#q3eM• \n0[NX/Tendstream endobj 142 0 obj << /Type /Page /Contents 143 0 R /Resources 141 0 R /MediaBox [0 0 609.714 789.041] /Parent 66 0 R >> endobj 144 0 obj << /D [142 0 R /XYZ 71.731 729.265 null] >> endobj 74 0 obj << /D [142 0 R /XYZ 71.731 718.306 null] >> endobj 34 0 obj << /D [142 0 R /XYZ 153.575 708.149 null] >> endobj 145 0 obj << /D [142 0 R /XYZ 71.731 700.797 null] >> endobj 146 0 obj << /D [142 0 R /XYZ 410.687 688.025 null] >> endobj 147 0 obj << /D [142 0 R /XYZ 472.335 675.073 null] >> endobj 141 0 obj << /Font << /F33 98 0 R /F23 45 0 R /F26 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 148 0 obj << /Type /Encoding /Differences [ 0 /.notdef 1/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring 10/.notdef 11/breve/minus 13/.notdef 14/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl 22/.notdef 30/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef 130/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE 141/.notdef 147/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe 157/.notdef 159/Ydieresis 160/.notdef 161/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] >> endobj 98 0 obj << /Type /Font /Subtype /Type1 /Encoding 148 0 R /BaseFont /Times-Italic >> endobj 82 0 obj << /Type /Font /Subtype /Type1 /Encoding 148 0 R /BaseFont /Courier >> endobj 56 0 obj << /Type /Font /Subtype /Type1 /Encoding 148 0 R /BaseFont /Times-Roman >> endobj 48 0 obj << /Type /Font /Subtype /Type1 /Encoding 148 0 R /BaseFont /Times-Bold >> endobj 45 0 obj << /Type /Font /Subtype /Type1 /Encoding 148 0 R /BaseFont /Helvetica-Bold >> endobj 66 0 obj << /Type /Pages /Count 5 /Kids [38 0 R 76 0 R 102 0 R 128 0 R 142 0 R] >> endobj 149 0 obj << /Type /Outlines /First 3 0 R /Last 3 0 R /Count 1 >> endobj 35 0 obj << /Title 36 0 R /A 33 0 R /Parent 3 0 R /Prev 31 0 R >> endobj 31 0 obj << /Title 32 0 R /A 29 0 R /Parent 3 0 R /Prev 15 0 R /Next 35 0 R >> endobj 27 0 obj << /Title 28 0 R /A 25 0 R /Parent 15 0 R /Prev 23 0 R >> endobj 23 0 obj << /Title 24 0 R /A 21 0 R /Parent 15 0 R /Prev 19 0 R /Next 27 0 R >> endobj 19 0 obj << /Title 20 0 R /A 17 0 R /Parent 15 0 R /Next 23 0 R >> endobj 15 0 obj << /Title 16 0 R /A 13 0 R /Parent 3 0 R /Prev 11 0 R /Next 31 0 R /First 19 0 R /Last 27 0 R /Count -3 >> endobj 11 0 obj << /Title 12 0 R /A 9 0 R /Parent 3 0 R /Prev 7 0 R /Next 15 0 R >> endobj 7 0 obj << /Title 8 0 R /A 5 0 R /Parent 3 0 R /Next 11 0 R >> endobj 3 0 obj << /Title 4 0 R /A 1 0 R /Parent 149 0 R /First 7 0 R /Last 35 0 R /Count -5 >> endobj 150 0 obj << /Names [(1.0) 2 0 R (1.1.1) 6 0 R (1.2.1) 10 0 R (1.3.1) 14 0 R (1.3.1.2) 18 0 R (1.3.2.2) 22 0 R (1.3.3.2) 26 0 R (1.4.1) 30 0 R (1.5.1) 34 0 R (15) 67 0 R (17) 79 0 R (18) 80 0 R (19) 83 0 R (20) 84 0 R (21) 85 0 R (22) 86 0 R (23) 87 0 R (24) 88 0 R (25) 68 0 R (27) 89 0 R (28) 90 0 R (29) 91 0 R (30) 92 0 R (31) 93 0 R (32) 94 0 R (33) 95 0 R (34) 96 0 R (35) 99 0 R (36) 100 0 R (37) 69 0 R (39) 70 0 R (41) 105 0 R (42) 106 0 R (43) 107 0 R (44) 108 0 R (45) 109 0 R (46) 110 0 R (47) 111 0 R (48) 112 0 R (49) 113 0 R (50) 114 0 R (51) 115 0 R (52) 116 0 R (53) 117 0 R (54) 71 0 R (56) 118 0 R (57) 119 0 R (58) 120 0 R (59) 121 0 R (60) 72 0 R (62) 122 0 R (63) 123 0 R (64) 124 0 R (65) 125 0 R (66) 126 0 R (67) 131 0 R (68) 132 0 R (69) 133 0 R (70) 134 0 R (71) 73 0 R (73) 135 0 R (74) 136 0 R (75) 137 0 R (76) 138 0 R (77) 139 0 R (78) 140 0 R (79) 74 0 R (81) 145 0 R (82) 146 0 R (83) 147 0 R (Doc-Start) 42 0 R (INDEX) 43 0 R (page.1) 41 0 R (page.2) 78 0 R (page.3) 104 0 R (page.4) 130 0 R (page.5) 144 0 R] /Limits [(1.0) (page.5)] >> endobj 151 0 obj << /Kids [150 0 R] >> endobj 152 0 obj << /Dests 151 0 R >> endobj 153 0 obj << /Type /Catalog /Pages 66 0 R /Outlines 149 0 R /Names 152 0 R /PageMode /UseOutlines /URI << /Base () >> /ViewerPreferences << >> /OpenAction 37 0 R >> endobj 154 0 obj << /Producer (pdfTeX-0.14h) /Author () /Title () /Subject () /Creator (LaTeX with hyperref package) /Producer (pdfTeX14.h) /Keywords () /Creator (TeX) /CreationDate (D:20031113120100) >> endobj xref 0 155 0000000044 65535 f 0000000009 00000 n 0000004613 00000 n 0000017920 00000 n 0000000048 00000 n 0000000083 00000 n 0000006582 00000 n 0000017850 00000 n 0000000124 00000 n 0000000167 00000 n 0000007172 00000 n 0000017766 00000 n 0000000208 00000 n 0000000243 00000 n 0000009761 00000 n 0000017643 00000 n 0000000285 00000 n 0000000315 00000 n 0000009881 00000 n 0000017569 00000 n 0000000359 00000 n 0000000387 00000 n 0000010795 00000 n 0000017482 00000 n 0000000431 00000 n 0000000459 00000 n 0000011160 00000 n 0000017408 00000 n 0000000503 00000 n 0000000532 00000 n 0000013213 00000 n 0000017322 00000 n 0000000574 00000 n 0000000617 00000 n 0000014501 00000 n 0000017249 00000 n 0000000659 00000 n 0000000689 00000 n 0000001825 00000 n 0000004668 00000 n 0000000739 00000 n 0000004436 00000 n 0000004495 00000 n 0000004554 00000 n 0000000047 00000 f 0000016992 00000 n 0000002065 00000 n 0000000055 00000 f 0000016902 00000 n 0000002212 00000 n 0000002361 00000 n 0000002509 00000 n 0000002658 00000 n 0000002805 00000 n 0000002953 00000 n 0000000081 00000 f 0000016811 00000 n 0000003101 00000 n 0000003250 00000 n 0000003398 00000 n 0000003547 00000 n 0000003695 00000 n 0000003844 00000 n 0000003992 00000 n 0000004141 00000 n 0000004288 00000 n 0000017086 00000 n 0000006523 00000 n 0000007114 00000 n 0000007826 00000 n 0000009822 00000 n 0000010735 00000 n 0000011100 00000 n 0000013153 00000 n 0000014441 00000 n 0000007884 00000 n 0000006348 00000 n 0000004762 00000 n 0000006464 00000 n 0000006641 00000 n 0000006700 00000 n 0000000097 00000 f 0000016724 00000 n 0000006760 00000 n 0000006819 00000 n 0000006878 00000 n 0000006938 00000 n 0000006998 00000 n 0000007057 00000 n 0000007232 00000 n 0000007291 00000 n 0000007351 00000 n 0000007410 00000 n 0000007469 00000 n 0000007529 00000 n 0000007588 00000 n 0000007647 00000 n 0000000000 00000 f 0000016632 00000 n 0000007707 00000 n 0000007766 00000 n 0000011527 00000 n 0000009581 00000 n 0000007990 00000 n 0000009700 00000 n 0000009942 00000 n 0000010003 00000 n 0000010063 00000 n 0000010124 00000 n 0000010185 00000 n 0000010247 00000 n 0000010308 00000 n 0000010369 00000 n 0000010431 00000 n 0000010492 00000 n 0000010553 00000 n 0000010613 00000 n 0000010674 00000 n 0000010855 00000 n 0000010916 00000 n 0000010978 00000 n 0000011039 00000 n 0000011221 00000 n 0000011282 00000 n 0000011343 00000 n 0000011405 00000 n 0000011467 00000 n 0000013640 00000 n 0000012727 00000 n 0000011634 00000 n 0000012846 00000 n 0000012907 00000 n 0000012968 00000 n 0000013030 00000 n 0000013092 00000 n 0000013274 00000 n 0000013335 00000 n 0000013396 00000 n 0000013457 00000 n 0000013518 00000 n 0000013579 00000 n 0000014747 00000 n 0000014261 00000 n 0000013747 00000 n 0000014380 00000 n 0000014562 00000 n 0000014623 00000 n 0000014685 00000 n 0000014842 00000 n 0000017176 00000 n 0000018015 00000 n 0000019094 00000 n 0000019133 00000 n 0000019171 00000 n 0000019346 00000 n trailer << /Size 155 /Root 153 0 R /Info 154 0 R >> startxref 19551 %%EOF pssh-2.3.4/doc/pssh-HOWTO.ps000066400000000000000000001400621364227332400154720ustar00rootroot00000000000000%!PS-Adobe-2.0 %%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software %%Title: pssh-HOWTO.dvi %%Pages: 5 %%PageOrder: Ascend %%BoundingBox: 0 0 596 842 %%DocumentFonts: Helvetica-Bold Times-Bold Times-Roman Courier %%+ Times-Italic %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -q pssh-HOWTO.dvi -o pssh-HOWTO.ps %DVIPSParameters: dpi=600, compressed %DVIPSSource: TeX output 2003.11.13:1201 %%BeginProcSet: texc.pro %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B /chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ /cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 {2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ 1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ /Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) (LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: 8r.enc % @@psencodingfile@{ % author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", % version = "0.6", % date = "22 June 1996", % filename = "8r.enc", % email = "kb@@mail.tug.org", % address = "135 Center Hill Rd. // Plymouth, MA 02360", % codetable = "ISO/ASCII", % checksum = "119 662 4424", % docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." % @} % % Idea is to have all the characters normally included in Type 1 fonts % available for typesetting. This is effectively the characters in Adobe % Standard Encoding + ISO Latin 1 + extra characters from Lucida. % % Character code assignments were made as follows: % % (1) the Windows ANSI characters are almost all in their Windows ANSI % positions, because some Windows users cannot easily reencode the % fonts, and it makes no difference on other systems. The only Windows % ANSI characters not available are those that make no sense for % typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen % (173). quotesingle and grave are moved just because it's such an % irritation not having them in TeX positions. % % (2) Remaining characters are assigned arbitrarily to the lower part % of the range, avoiding 0, 10 and 13 in case we meet dumb software. % % (3) Y&Y Lucida Bright includes some extra text characters; in the % hopes that other PostScript fonts, perhaps created for public % consumption, will include them, they are included starting at 0x12. % % (4) Remaining positions left undefined are for use in (hopefully) % upward-compatible revisions, if someday more characters are generally % available. % % (5) hyphen appears twice for compatibility with both ASCII and Windows. % /TeXBase1Encoding [ % 0x00 (encoded characters from Adobe Standard not in Windows 3.1) /.notdef /dotaccent /fi /fl /fraction /hungarumlaut /Lslash /lslash /ogonek /ring /.notdef /breve /minus /.notdef % These are the only two remaining unencoded characters, so may as % well include them. /Zcaron /zcaron % 0x10 /caron /dotlessi % (unusual TeX characters available in, e.g., Lucida Bright) /dotlessj /ff /ffi /ffl /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef % very contentious; it's so painful not having quoteleft and quoteright % at 96 and 145 that we move the things normally found there down to here. /grave /quotesingle % 0x20 (ASCII begins) /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash % 0x30 /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question % 0x40 /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O % 0x50 /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore % 0x60 /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o % 0x70 /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef % rubout; ASCII ends % 0x80 /.notdef /.notdef /quotesinglbase /florin /quotedblbase /ellipsis /dagger /daggerdbl /circumflex /perthousand /Scaron /guilsinglleft /OE /.notdef /.notdef /.notdef % 0x90 /.notdef /.notdef /.notdef /quotedblleft /quotedblright /bullet /endash /emdash /tilde /trademark /scaron /guilsinglright /oe /.notdef /.notdef /Ydieresis % 0xA0 /.notdef % nobreakspace /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen % Y&Y (also at 45); Windows' softhyphen /registered /macron % 0xD0 /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown % 0xC0 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis % 0xD0 /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls % 0xE0 /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis % 0xF0 /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis ] def %%EndProcSet %%BeginProcSet: texps.pro %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics exch def dict begin Encoding{exch dup type/integertype ne{pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} ifelse}forall Metrics/Metrics currentdict end def[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{ dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[exch{dup CharStrings exch known not{pop/.notdef/Encoding true def} if}forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def} def end %%EndProcSet %%BeginProcSet: special.pro %! TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N /vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N /rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N /@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{ /hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B /@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{ /urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known {userdict/md get type/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup length 20 add dict copy def}if end md begin /letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{ itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack} if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{ noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{ Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale }if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState save N userdict maxlength dict begin/magscale true def normalscale currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts /psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR/showpage{}N/erasepage{}N/copypage{}N/p 3 def @MacSetUp}N/doclip{ psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath moveto}N/endTexFig{end psf$SavedState restore}N/@beginspecial{SDict begin/SpecialSave save N gsave normalscale currentpoint TR @SpecialDefaults count/ocount X/dcount countdictstack N}N/@setspecial{ CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR }{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury lineto closepath clip}if/showpage{}N/erasepage{}N/copypage{}N newpath}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{end} repeat grestore SpecialSave restore end}N/@defspecial{SDict begin}N /@fedspecial{end}B/li{lineto}B/rl{rlineto}B/rc{rcurveto}B/np{/SaveX currentpoint/SaveY X N 1 setlinecap newpath}N/st{stroke SaveX SaveY moveto}N/fil{fill SaveX SaveY moveto}N/ellipse{/endangle X/startangle X /yrad X/xrad X/savematrix matrix currentmatrix N TR xrad yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end %%EndProcSet %%BeginProcSet: color.pro %! TeXDict begin/setcmykcolor where{pop}{/setcmykcolor{dup 10 eq{pop setrgbcolor}{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll }repeat setrgbcolor pop}ifelse}B}ifelse/TeXcolorcmyk{setcmykcolor}def /TeXcolorrgb{setrgbcolor}def/TeXcolorgrey{setgray}def/TeXcolorgray{ setgray}def/TeXcolorhsb{sethsbcolor}def/currentcmykcolor where{pop}{ /currentcmykcolor{currentrgbcolor 10}B}ifelse/DC{exch dup userdict exch known{pop pop}{X}ifelse}B/GreenYellow{0.15 0 0.69 0 setcmykcolor}DC /Yellow{0 0 1 0 setcmykcolor}DC/Goldenrod{0 0.10 0.84 0 setcmykcolor}DC /Dandelion{0 0.29 0.84 0 setcmykcolor}DC/Apricot{0 0.32 0.52 0 setcmykcolor}DC/Peach{0 0.50 0.70 0 setcmykcolor}DC/Melon{0 0.46 0.50 0 setcmykcolor}DC/YellowOrange{0 0.42 1 0 setcmykcolor}DC/Orange{0 0.61 0.87 0 setcmykcolor}DC/BurntOrange{0 0.51 1 0 setcmykcolor}DC /Bittersweet{0 0.75 1 0.24 setcmykcolor}DC/RedOrange{0 0.77 0.87 0 setcmykcolor}DC/Mahogany{0 0.85 0.87 0.35 setcmykcolor}DC/Maroon{0 0.87 0.68 0.32 setcmykcolor}DC/BrickRed{0 0.89 0.94 0.28 setcmykcolor}DC/Red{ 0 1 1 0 setcmykcolor}DC/OrangeRed{0 1 0.50 0 setcmykcolor}DC/RubineRed{ 0 1 0.13 0 setcmykcolor}DC/WildStrawberry{0 0.96 0.39 0 setcmykcolor}DC /Salmon{0 0.53 0.38 0 setcmykcolor}DC/CarnationPink{0 0.63 0 0 setcmykcolor}DC/Magenta{0 1 0 0 setcmykcolor}DC/VioletRed{0 0.81 0 0 setcmykcolor}DC/Rhodamine{0 0.82 0 0 setcmykcolor}DC/Mulberry{0.34 0.90 0 0.02 setcmykcolor}DC/RedViolet{0.07 0.90 0 0.34 setcmykcolor}DC /Fuchsia{0.47 0.91 0 0.08 setcmykcolor}DC/Lavender{0 0.48 0 0 setcmykcolor}DC/Thistle{0.12 0.59 0 0 setcmykcolor}DC/Orchid{0.32 0.64 0 0 setcmykcolor}DC/DarkOrchid{0.40 0.80 0.20 0 setcmykcolor}DC/Purple{ 0.45 0.86 0 0 setcmykcolor}DC/Plum{0.50 1 0 0 setcmykcolor}DC/Violet{ 0.79 0.88 0 0 setcmykcolor}DC/RoyalPurple{0.75 0.90 0 0 setcmykcolor}DC /BlueViolet{0.86 0.91 0 0.04 setcmykcolor}DC/Periwinkle{0.57 0.55 0 0 setcmykcolor}DC/CadetBlue{0.62 0.57 0.23 0 setcmykcolor}DC /CornflowerBlue{0.65 0.13 0 0 setcmykcolor}DC/MidnightBlue{0.98 0.13 0 0.43 setcmykcolor}DC/NavyBlue{0.94 0.54 0 0 setcmykcolor}DC/RoyalBlue{1 0.50 0 0 setcmykcolor}DC/Blue{1 1 0 0 setcmykcolor}DC/Cerulean{0.94 0.11 0 0 setcmykcolor}DC/Cyan{1 0 0 0 setcmykcolor}DC/ProcessBlue{0.96 0 0 0 setcmykcolor}DC/SkyBlue{0.62 0 0.12 0 setcmykcolor}DC/Turquoise{0.85 0 0.20 0 setcmykcolor}DC/TealBlue{0.86 0 0.34 0.02 setcmykcolor}DC /Aquamarine{0.82 0 0.30 0 setcmykcolor}DC/BlueGreen{0.85 0 0.33 0 setcmykcolor}DC/Emerald{1 0 0.50 0 setcmykcolor}DC/JungleGreen{0.99 0 0.52 0 setcmykcolor}DC/SeaGreen{0.69 0 0.50 0 setcmykcolor}DC/Green{1 0 1 0 setcmykcolor}DC/ForestGreen{0.91 0 0.88 0.12 setcmykcolor}DC /PineGreen{0.92 0 0.59 0.25 setcmykcolor}DC/LimeGreen{0.50 0 1 0 setcmykcolor}DC/YellowGreen{0.44 0 0.74 0 setcmykcolor}DC/SpringGreen{ 0.26 0 0.76 0 setcmykcolor}DC/OliveGreen{0.64 0 0.95 0.40 setcmykcolor} DC/RawSienna{0 0.72 1 0.45 setcmykcolor}DC/Sepia{0 0.83 1 0.70 setcmykcolor}DC/Brown{0 0.81 1 0.60 setcmykcolor}DC/Tan{0.14 0.42 0.56 0 setcmykcolor}DC/Gray{0 0 0 0.50 setcmykcolor}DC/Black{0 0 0 1 setcmykcolor}DC/White{0 0 0 0 setcmykcolor}DC end %%EndProcSet TeXDict begin 39158280 55380996 1000 600 600 (pssh-HOWTO.dvi) @start /Fa 138[61 1[55 2[61 1[61 2[55 2[61 2[55 1[55 47[55 55 55 2[28 46[{TeXBase1Encoding ReEncodeFont}12 99.6264 /Helvetica-Bold rf /Fb 136[55 2[23 32 32 1[42 42 42 1[23 2[23 42 42 1[37 42 2[42 9[69 2[46 4[60 6[60 18[42 42 42 42 4[28 45[{TeXBase1Encoding ReEncodeFont}23 83.022 /Times-Italic rf /Fc 133[45 45 45 45 45 45 45 45 45 1[45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 1[45 1[45 1[45 4[45 45 45 45 45 1[45 45 45 1[45 45 1[45 45 1[45 45 45 1[45 45 3[45 2[45 45 45 1[45 45 1[45 45 45 45 45 45 45 2[45 45 45 2[45 45 45 45 34[{ TeXBase1Encoding ReEncodeFont}65 74.7198 /Courier rf /Fd 135[66 1[66 73 40 66 47 1[73 73 73 106 33 66 1[33 3[66 73 66 73 66 10[80 2[80 2[80 6[33 2[73 80 15[66 66 66 66 66 2[33 46[{TeXBase1Encoding ReEncodeFont}30 119.552 /Helvetica-Bold rf /Fe 134[42 42 60 42 42 23 32 28 1[42 42 42 65 23 42 23 23 42 42 28 37 42 37 42 37 11[60 51 46 55 1[46 1[60 1[51 2[28 60 1[46 2[55 55 60 6[23 6[42 42 42 1[23 21 28 21 2[28 28 28 5[28 30[46 2[{ TeXBase1Encoding ReEncodeFont}50 83.022 /Times-Roman rf /Ff 135[42 1[42 46 28 32 37 1[46 42 46 69 23 46 1[23 3[37 46 37 46 42 10[60 2[46 2[51 6[32 2[51 55 15[42 42 42 42 42 2[21 46[{TeXBase1Encoding ReEncodeFont}30 83.022 /Times-Bold rf /Fg 138[88 48 80 56 2[88 88 1[40 3[88 1[48 80 2[88 80 12[88 16[104 104 66[{TeXBase1Encoding ReEncodeFont}15 143.462 /Helvetica-Bold rf /Fh 140[115 2[126 7[126 16[195 2[126 4[161 6[149 72[{TeXBase1Encoding ReEncodeFont}7 206.584 /Helvetica-Bold rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%PaperSize: A4 %%EndSetup %%Page: 1 1 1 0 bop Black 0 TeXcolorgray Black Black 1284 140 a Fh(pssh)58 b(HO)-10 b(WT)i(O)1550 416 y Fg(Brent)38 b(Chun)-2 1175 y(T)-11 b(ab)o(le)37 b(of)j(Contents)p 0 TeXcolorgray -2 1355 a Ff(1.)20 b(Installation)g(and)g(Setup)p Black Black 4 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black 0 TeXcolorgray 4 w(2)p Black 0 TeXcolorgray -2 1483 a(2.)g(Pr)o(eliminaries)p Black Black 19 w(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black 0 TeXcolorgray 4 w(2)p Black 0 TeXcolorgray -2 1611 a(3.)g(Examples)p Black Black 7 w(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black 0 TeXcolorgray 4 w(2)p Black 0 TeXcolorgray 197 1739 a Fe(3.1.)f(pssh)p Black Black 6 w(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black 0 TeXcolorgray 4 w(3)p Black 0 TeXcolorgray 197 1846 a(3.2.)g(pscp)p Black Black 1 w(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black 0 TeXcolorgray 4 w(3)p Black 0 TeXcolorgray 197 1954 a(3.3.)g(pnuk)o(e)p Black Black 14 w(.)p Black Black -2 w(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black 0 TeXcolorgray 4 w(3)p Black 0 TeXcolorgray -2 2082 a Ff(4.)h(En)m(vir)o(onment)f(V)-8 b(ariables)p Black Black 10 w(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black 0 TeXcolorgray 4 w(4)p Black 0 TeXcolorgray -2 2210 a(5.)20 b(F)n(eedback)p Black Black 14 w(.)p Black Black -2 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black(.)p Black Black -1 w(.)p Black Black(.)p Black Black(.)p Black 0 TeXcolorgray 4 w(5)p Black Black Black eop %%Page: 2 2 2 1 bop Black 0 TeXcolorgray Black Black -2 77 a Fd(1.)34 b(Installation)h(and)f(Setup)-2 244 y Fe(T)-7 b(o)20 b(install)h(the)f(softw)o(are,)g(become)f Fc(root)h Fe(on)f(your)g (machine)g(and)h(do)g(the)g(follo)n(wing)f(\(on)g(RedHat)h(systems\):) 132 425 y Fc(#)45 b(rpm)f(-ivh)g(pssh-0.2.3-1.i386.rpm)132 522 y(Preparing...)716 b(####################################)o(######) o(#)39 b([100\045])267 619 y(1:pssh)851 b (####################################)o(######)o(#)39 b([100\045])-2 810 y Fe(By)20 b(def)o(ault,)g(the)g(softw)o(are)g (installs)h(itself)f(in)h Fc(/usr/localbin)d Fe(and)i Fc(/usr/local/lib)p Fe(.)e(Thus,)i(you')o(ll)f(ne)o(xt)g(w)o(ant)i(to)f (modify)-2 918 y(your)f Fc(PATH)h Fe(if)g(needed:)-2 1098 y Fc(#)44 b(export)g(PATH=$PATH:/usr/local/bin)-2 1509 y Fd(2.)34 b(Preliminaries)-2 1677 y Fe(All)21 b(four)e(programs)f (will)j(print)f(their)f(usage)h(and)g(gi)n(v)o(e)f(an)h(e)o(xample)f (if)i(no)e(ar)o(guments)g(are)h(gi)n(v)o(en.)e(F)o(or)i(e)o(xample,)f (with)h Fc(pssh)p Fe(:)132 1857 y Fc(#)45 b(pssh)132 1954 y(Usage:)f(pssh)g([OPTIONS])g(-h)g(hosts.txt)f(prog)i([arg0])e(..) 222 2148 y(-h)h(--hosts)134 b(hosts)44 b(file)g(\(each)g(line)g ("host[:port])f([user]"\))222 2245 y(-l)h(--user)179 b(username)43 b(\(OPTIONAL\))222 2343 y(-p)h(--par)224 b(max)44 b(number)g(of)g(parallel)g(threads)g(\(OPTIONAL\))222 2440 y(-o)g(--outdir)89 b(output)44 b(directory)f(for)h(stdout)g(files) g(\(OPTIONAL\))222 2537 y(-t)g(--timeout)g(timeout)f(in)i(seconds)f(to) g(do)h(ssh)f(to)g(a)h(host)f(\(OPTIONAL\))222 2634 y(-v)g(--verbose)g (turn)g(on)g(warning)g(and)g(diagnostic)g(messages)f(\(OPTIONAL\))222 2731 y(-O)h(--options)g(SSH)g(options)g(\(OPTIONAL\))132 2925 y(Example:)g(pssh)g(-h)g(ips.txt)g(-l)h(irb2)f(-o)g(/tmp/foo)g (uptime)-2 3116 y Fe(And)19 b(for)h Fc(pscp)p Fe(:)132 3296 y Fc(#)45 b(pscp)132 3394 y(Usage:)f(pscp)g([OPTIONS])g(-h)g (hosts.txt)f(local)h(remote)222 3588 y(-h)g(--hosts)223 b(hosts)44 b(file)h(\(each)f(line)g("host[:port])f([login]"\))222 3685 y(-r)h(--recursive)f(recusively)h(copy)g(directories)f (\(OPTIONAL\))222 3782 y(-l)h(--user)268 b(username)44 b(\(OPTIONAL\))222 3879 y(-p)g(--par)313 b(max)45 b(number)f(of)g (parallel)g(threads)f(\(OPTIONAL\))222 3976 y(-t)h(--timeout)133 b(timeout)44 b(in)h(seconds)e(to)i(do)f(scp)h(to)f(a)h(host)f (\(OPTIONAL\))222 4074 y(-O)g(--options)133 b(SSH)45 b(options)e(\(OPTIONAL\))132 4268 y(Example:)h(pscp)g(-h)g(hosts.txt)g (-l)g(irb2)g(foo.txt)g(/home/irb2/foo.txt)-2 4459 y Fe(Note)20 b(that)g(before)f(using)h(an)o(y)f(of)h(these)g(tools,)g(you)g Fb(will)h(need)e(to)i(start)g(ssh-a)o(g)o(ent)q Fe(!)e(This)i(can)f(be) g(done)f(as)i(follo)n(ws)f(\(substitute)-2 4567 y Fc(zsh)g Fe(with)g(your)f(particular)g(shell\).)132 4747 y Fc(#)45 b(ssh-agent)e(zsh)132 4844 y(#)i(ssh-add)132 4941 y(Enter)f(passphrase) f(for)i(/x/bnc/.ssh/identity:)p Black 3842 5569 a Fb(2)p Black eop %%Page: 3 3 3 2 bop Black 0 TeXcolorgray Black 3425 -132 a Fb(pssh)21 b(HO)l(WT)o(O)p Black -2 74 a Fd(3.)34 b(Examples)-2 361 y Fa(3.1.)28 b(pssh)-2 519 y Fe(The)20 b(follo)n(wing)e(e)o(xample) h(runs)h Fc(hostname)f Fe(on)h(three)g(machines)f(\(IPs)h(or)g (hostnames\))f(speci\002ed)h(in)g(the)h(\002le)g Fc(ips.txt)e Fe(using)-2 627 y(login)g Fc(irb2)h Fe(and)g(sa)n(v)o(es)h(the)f (output)f(in)h Fc(/tmp/foo)p Fe(.)132 807 y Fc(#)45 b(cat)f(ips.txt)132 904 y(128.112.152.122)132 1001 y(18.31.0.190)132 1099 y(128.232.103.201)132 1293 y(#)h(pssh)f(-h)h(ips.txt)e(-l)i(irb2)f(-o)g (/tmp/foo)g(hostname)132 1390 y(Success)g(on)g(128.112.152.122:22)132 1487 y(Success)g(on)g(18.31.0.190:22)132 1584 y(Success)g(on)g (128.232.103.201:22)132 1779 y(#)h(ls)f(/tmp/foo)132 1876 y(128.112.152.122)87 b(128.232.103.201)h(18.31.0.190)132 2070 y(#)45 b(cat)f(/tmp/foo/*)132 2167 y(planetlab-1.cs.princeton.edu) 132 2264 y(planetlab1.xeno.cl.cam.ac.uk)132 2361 y (planetlab1.lcs.mit.edu)-2 2552 y Fe(By)20 b(def)o(ault,)g Fc(pssh)g Fe(uses)g(at)h(most)f(32)g(ssh)h(processes)f(in)g(parallel)g (to)g(ssh)h(to)g(the)f(v)n(arious)f(nodes.)g(\(This)h(is)h(some)n(what) e(important)g(if)-2 2660 y(you')l(re)f(controlling)g(hundreds)g(or)i (thousands)f(of)h(machines.\))f(By)h(def)o(ault,)g(it)g(also)h(uses)g (a)f(timeout)g(of)g(one)f(minute)h(to)g(ssh)h(to)f(a)-2 2768 y(node)f(and)h(obtain)f(a)h(result.)g(F)o(or)g(ssh)h(commands)e (that)h(tak)o(e)g(longer)f(than)h(this)g(\(e.g.,)g Fc(sleep)43 b(61)p Fe(\),)20 b(the)h(-t)f(option)f(can)h(be)g(used.)-2 2876 y(Note)g(that)g Fc(pssh)g Fe(and)g Fc(pnuke)g Fe(ha)n(v)o(e)f(a)i (def)o(ault)f(timeout)f(of)h(one)g(minute.)f Fc(pscp)h Fe(and)f Fc(prsync)h Fe(ha)n(v)o(e)g(no)g(def)o(ault)f(timeout,)g(b)n (ut)h(one)-2 2984 y(can)g(be)g(speci\002ed)g(using)f(the)i(-t)f (option.)-2 3321 y Fa(3.2.)28 b(pscp)-2 3479 y Fe(Here')-5 b(s)20 b(an)g(e)o(xample)f(of)h(using)g Fc(pscp)g Fe(to)g(cop)o(y)f (\002les)j(in)e(parallel)g(to)g(a)h(set)g(of)f(machines.)132 3659 y Fc(#)45 b(pscp)f(-h)h(ips.txt)e(-l)i(irb2)f(/etc/hosts)f (/tmp/hosts)132 3756 y(Success)h(on)g(128.112.152.122:22)132 3853 y(Success)g(on)g(18.31.0.190:22)132 3950 y(Success)g(on)g (128.232.103.201:22)-2 4141 y Fe(Using)20 b(the)g(-r)g(option)f(will)i (perform)d(a)j(recursi)n(v)o(e)d(cop)o(y)i(for)f(cop)o(ying)g(entire)h (directories.)-2 4478 y Fa(3.3.)28 b(pn)o(uke)-2 4636 y Fe(The)20 b Fc(pnuke)g Fe(command)e(is)j(useful)f(when)f(you)g(w)o (ant)i(to)f(kill)h(a)f(b)n(unch)f(of)h(processes)g(on)g(a)g(set)h(of)f (machines.)f(F)o(or)h(e)o(xample,)-2 4744 y(suppose)f(you')l(v)o(e)f (got)i(a)g(b)n(unch)f(of)h Fc(java)g Fe(processes)g(running)e(on)i (three)g(nodes)f(that)i(you')l(d)d(lik)o(e)i(to)h(nuk)o(e)e(\(let')-5 b(s)21 b(use)f(the)g(three)-2 4852 y(machines)f(from)g(the)h Fc(pssh)h Fe(e)o(xample\).)d(Here)i(you)f(w)o(ould)h(do)f(the)i(follo)n (wing:)132 5032 y Fc(#)45 b(pnuke)f(-h)g(ips.txt)g(-l)h(irb2)f(java)132 5129 y(Success)g(on)g(128.112.152.122:22)p Black 3842 5569 a Fb(3)p Black eop %%Page: 4 4 4 3 bop Black 0 TeXcolorgray Black 3425 -132 a Fb(pssh)21 b(HO)l(WT)o(O)p Black 132 72 a Fc(Success)44 b(on)g(18.31.0.190:22)132 170 y(Success)g(on)g(128.232.103.201:22)-2 361 y Fe(The)20 b(result)g(of)g(the)g(abo)o(v)o(e)e(is)k(to)e(send)g Fc(kill)44 b(-9)20 b Fe(to)h(all)g(processes)e(o)n(wned)g(by)h Fc(irb2)g Fe(with)h(the)f(string)g(ja)n(v)n(a)g(in)g(their)g(name)g (\(as)-2 468 y(reported)e(by)i Fc(ps)44 b(-ef)p Fe(\).)-2 921 y Fd(4.)34 b(En)-5 b(vir)n(onment)33 b(V)-7 b(ariab)o(les)-2 1089 y Fe(All)21 b(four)e(programs)f(tak)o(e)i(similar)h(sets)g(of)f (options.)f(All)i(of)f(these)g(options)f(can)h(be)g(set)h(using)f(the)g (follo)n(wing)f(en)m(vironment)-2 1197 y(v)n(ariables:)132 1377 y Fc(PSSH_HOSTS)132 1474 y(PSSH_USER)132 1571 y(PSSH_PAR)132 1668 y(PSSH_OUTDIR)132 1765 y(PSSH_VERBOSE)132 1863 y(PSSH_OPTIONS)-2 2054 y Fe(Here)h(are)g(some)g(e)o(xample)f(settings:)132 2234 y Fc(#)45 b(export)f(PSSH_HOSTS="/x/bnc/ips.txt")132 2331 y(#)h(export)f(PSSH_USER="irb2")132 2428 y(#)h(export)f (PSSH_PAR="32")132 2525 y(#)h(export)f(PSSH_OUTDIR="/tmp/bar")132 2622 y(#)h(export)f(PSSH_VERBOSE="0")132 2719 y(#)h(export)f (PSSH_OPTIONS="UserKnownHostsFile)39 b(/tmp/known_hosts")-2 2910 y Fe(Using)20 b(the)g(abo)o(v)o(e)f(settings,)h(the)g(e)o(xamples) f(can)h(be)g(e)o(x)o(ecuted)f(succinctly)g(as:)132 3090 y Fc(#)45 b(pssh)f(hostname)132 3188 y(Success)g(on)g (128.112.152.122:22)132 3285 y(Success)g(on)g(18.31.0.190:22)132 3382 y(Success)g(on)g(128.232.103.201:22)132 3576 y(#)h(ls)f(/tmp/bar) 132 3673 y(128.112.152.122)87 b(128.232.103.201)h(18.31.0.190)132 3868 y(#)45 b(cat)f(/tmp/bar/*)132 3965 y(planetlab-1.cs.princeton.edu) 132 4062 y(planetlab1.xeno.cl.cam.ac.uk)132 4159 y (planetlab1.lcs.mit.edu)132 4353 y(#)h(pscp)f(/etc/hosts)f(/tmp/hosts) 132 4450 y(Success)h(on)g(128.112.152.122:22)132 4548 y(Success)g(on)g(18.31.0.190:22)132 4645 y(Success)g(on)g (128.232.103.201:22)132 4839 y(#)h(pnuke)f(java)132 4936 y(Success)g(on)g(128.112.152.122:22)132 5033 y(Success)g(on)g (18.31.0.190:22)132 5130 y(Success)g(on)g(128.232.103.201:22)p Black 3842 5569 a Fb(4)p Black eop %%Page: 5 5 5 4 bop Black 0 TeXcolorgray Black 3425 -132 a Fb(pssh)21 b(HO)l(WT)o(O)p Black -2 74 a Fd(5.)34 b(Feedbac)n(k)-2 242 y Fe(Send)20 b(me)g(email)g(if)g(you')l(re)f(ha)n(ving)g(problems,) f(\002nd)i(b)n(ugs,)g(or)g(ha)n(v)o(e)f(an)o(y)h(random)e(comments:)h (Brent)i(Chun)-2 350 y(\(http://www)-5 b(.theether)g(.or)o(g\))15 b(\(bnc)k(at)i(theether)-5 b(.or)o(g\).)17 b(Thus)j(f)o(ar)m(,)f(I')l (v)o(e)g(primarily)g(been)h(testing)g(this)h(softw)o(are)e(on)h (PlanetLab)-2 458 y(\(http://www)-5 b(.planet-lab)m(.or)o(g\))o(.)p Black 3842 5569 a Fb(5)p Black eop %%Trailer end userdict /end-hook known{end-hook}if %%EOF pssh-2.3.4/doc/pssh-HOWTO.sgml000066400000000000000000000160031364227332400160070ustar00rootroot00000000000000
pssh HOWTO 0.1, 2003-11-13 Brent Chun 0.1 2003-11-13 Initial version. Installation and Setup To install the software, become root on your machine and do the following (on RedHat systems): # rpm -ivh pssh-0.2.3-1.i386.rpm Preparing... ########################################### [100%] 1:pssh ########################################### [100%] By default, the software installs itself in /usr/localbin and /usr/local/lib. Thus, you'll next want to modify your PATH if needed: # export PATH=$PATH:/usr/local/bin Preliminaries All four programs will print their usage and give an example if no arguments are given. For example, with pssh: # pssh Usage: pssh [OPTIONS] -h hosts.txt prog [arg0] .. -h --hosts hosts file (each line "host[:port] [user]") -l --user username (OPTIONAL) -p --par max number of parallel threads (OPTIONAL) -o --outdir output directory for stdout files (OPTIONAL) -t --timeout timeout in seconds to do ssh to a host (OPTIONAL) -v --verbose turn on warning and diagnostic messages (OPTIONAL) -O --options SSH options (OPTIONAL) Example: pssh -h ips.txt -l irb2 -o /tmp/foo uptime And for pscp: # pscp Usage: pscp [OPTIONS] -h hosts.txt local remote -h --hosts hosts file (each line "host[:port] [login]") -r --recursive recusively copy directories (OPTIONAL) -l --user username (OPTIONAL) -p --par max number of parallel threads (OPTIONAL) -t --timeout timeout in seconds to do scp to a host (OPTIONAL) -O --options SSH options (OPTIONAL) Example: pscp -h hosts.txt -l irb2 foo.txt /home/irb2/foo.txt Note that before using any of these tools, you will need to start ssh-agent! This can be done as follows (substitute zsh with your particular shell). # ssh-agent zsh # ssh-add Enter passphrase for /x/bnc/.ssh/identity: Examples pssh The following example runs hostname on three machines (IPs or hostnames) specified in the file ips.txt using login irb2 and saves the output in /tmp/foo. # cat ips.txt 128.112.152.122 18.31.0.190 128.232.103.201 # pssh -h ips.txt -l irb2 -o /tmp/foo hostname Success on 128.112.152.122:22 Success on 18.31.0.190:22 Success on 128.232.103.201:22 # ls /tmp/foo 128.112.152.122 128.232.103.201 18.31.0.190 # cat /tmp/foo/* planetlab-1.cs.princeton.edu planetlab1.xeno.cl.cam.ac.uk planetlab1.lcs.mit.edu By default, pssh uses at most 32 ssh processes in parallel to ssh to the various nodes. (This is somewhat important if you're controlling hundreds or thousands of machines.) By default, it also uses a timeout of one minute to ssh to a node and obtain a result. For ssh commands that take longer than this (e.g., sleep 61), the -t option can be used. Note that pssh and pnuke have a default timeout of one minute. pscp and prsync have no default timeout, but one can be specified using the -t option. pscp Here's an example of using pscp to copy files in parallel to a set of machines. # pscp -h ips.txt -l irb2 /etc/hosts /tmp/hosts Success on 128.112.152.122:22 Success on 18.31.0.190:22 Success on 128.232.103.201:22 Using the -r option will perform a recursive copy for copying entire directories. pnuke The pnuke command is useful when you want to kill a bunch of processes on a set of machines. For example, suppose you've got a bunch of java processes running on three nodes that you'd like to nuke (let's use the three machines from the pssh example). Here you would do the following: # pnuke -h ips.txt -l irb2 java Success on 128.112.152.122:22 Success on 18.31.0.190:22 Success on 128.232.103.201:22 The result of the above is to send kill -9 to all processes owned by irb2 with the string java in their name (as reported by ps -ef). Environment Variables All four programs take similar sets of options. All of these options can be set using the following environment variables: PSSH_HOSTS PSSH_USER PSSH_PAR PSSH_OUTDIR PSSH_VERBOSE PSSH_OPTIONS Here are some example settings: # export PSSH_HOSTS="/x/bnc/ips.txt" # export PSSH_USER="irb2" # export PSSH_PAR="32" # export PSSH_OUTDIR="/tmp/bar" # export PSSH_VERBOSE="0" # export PSSH_OPTIONS="UserKnownHostsFile /tmp/known_hosts" Using the above settings, the examples can be executed succinctly as: # pssh hostname Success on 128.112.152.122:22 Success on 18.31.0.190:22 Success on 128.232.103.201:22 # ls /tmp/bar 128.112.152.122 128.232.103.201 18.31.0.190 # cat /tmp/bar/* planetlab-1.cs.princeton.edu planetlab1.xeno.cl.cam.ac.uk planetlab1.lcs.mit.edu # pscp /etc/hosts /tmp/hosts Success on 128.112.152.122:22 Success on 18.31.0.190:22 Success on 128.232.103.201:22 # pnuke java Success on 128.112.152.122:22 Success on 18.31.0.190:22 Success on 128.232.103.201:22 Feedback Send me email if you're having problems, find bugs, or have any random comments: Brent Chun (bnc at theether.org). Thus far, I've primarily been testing this software on PlanetLab.
pssh-2.3.4/man/000077500000000000000000000000001364227332400132565ustar00rootroot00000000000000pssh-2.3.4/man/man1/000077500000000000000000000000001364227332400141125ustar00rootroot00000000000000pssh-2.3.4/man/man1/pnuke.1000066400000000000000000000125711364227332400153240ustar00rootroot00000000000000.\" Man page for pssh. See "man 7 man" and "man man-pages" for formatting info. .TH pnuke 1 "January 24, 2012" .SH NAME pnuke \(em parallel process kill program .SH SYNOPSIS .B pnuke .RB [ \-vA ] .RB [ \-h .IR hosts_file ] .RB [ \-H .RI [ user @] host [: port ]] .RB [ \-l .IR user ] .RB [ \-p .IR par ] .RB [ \-o .IR outdir ] .RB [ \-e .IR errdir ] .RB [ \-t .IR timeout ] .RB [ \-O .IR options ] .RB [ \-x .IR args ] .RB [ \-X .IR arg ] .I pattern .SH DESCRIPTION .PP .B pnuke is a program for killing processes in parallel on a number of hosts. It provides features such as passing a password to ssh, saving output to files, and timing out. .SH OPTIONS .TP .BI \-h " host_file" .PD 0 .TP .BI \-\-hosts " host_file" Read hosts from the given .IR host_file . Lines in the host file are of the form .RI [ user @] host [: port ] and can include blank lines and comments (lines beginning with "#"). If multiple host files are given (the .B \-h option is used more than once), then pnuke behaves as though these files were concatenated together. If a host is specified multiple times, then pnuke will connect the given number of times. .TP .B \-H .RI [ user @] host [: port ] .PD 0 .TP .B \-\-host .RI [ user @] host [: port ] .PD 0 .TP .B \-H .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .TP .B \-\-host .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .IP Add the given host strings to the list of hosts. This option may be given multiple times, and may be used in conjunction with the .B \-h option. .TP .BI \-l " user" .PD 0 .TP .BI \-\-user " user" Use the given username as the default for any host entries that don't specifically specify a user. .TP .BI \-p " parallelism" .PD 0 .TP .BI \-\-par " parallelism" Use the given number as the maximum number of concurrent connections. .TP .BI \-t " timeout" .PD 0 .TP .BI \-\-timeout " timeout" Make connections time out after the given number of seconds. With a value of 0, pnuke will not timeout any connections. .TP .BI \-o " outdir" .PD 0 .TP .BI \-\-outdir " outdir" Save standard output to files in the given directory. Filenames are of the form .RI [ user @] host [: port ][. num ] where the user and port are only included for hosts that explicitly specify them. The number is a counter that is incremented each time for hosts that are specified more than once. .TP .BI \-e " errdir" .PD 0 .TP .BI \-\-errdir " errdir" Save standard error to files in the given directory. Filenames are of the same form as with the .B \-o option. .TP .BI \-x " args" .PD 0 .TP .BI \-\-extra-args " args" Passes extra SSH command-line arguments (see the .BR ssh (1) man page for more information about SSH arguments). This option may be specified multiple times. The arguments are processed to split on whitespace, protect text within quotes, and escape with backslashes. To pass arguments without such processing, use the .B \-X option instead. .TP .BI \-X " arg" .PD 0 .TP .BI \-\-extra-arg " arg" Passes a single SSH command-line argument (see the .BR ssh (1) man page for more information about SSH arguments). Unlike the .B \-x option, no processing is performed on the argument, including word splitting. To pass multiple command-line arguments, use the option once for each argument. .TP .BI \-O " options" .PD 0 .TP .BI \-\-options " options" SSH options in the format used in the SSH configuration file (see the .BR ssh_config (5) man page for more information). This option may be specified multiple times. .TP .B \-A .PD 0 .TP .B \-\-askpass Prompt for a password and pass it to ssh. The password may be used for either to unlock a key or for password authentication. The password is transferred in a fairly secure manner (e.g., it will not show up in argument lists). However, be aware that a root user on your system could potentially intercept the password. .TP .B \-v .PD 0 .TP .B \-\-verbose Include error messages from ssh with the .B \-i and .B \e options. .\" .SH EXAMPLES .\" .PP .\" Connect to host1 and host2, and print "hello, world" from each: .\" .RS .\" pssh -i -H "host1 host2" echo "hello, world" .\" .RE .SH TIPS .\" .PP .\" If you have a set of hosts that you connect to frequently with specific .\" options, it may be helpful to create an alias such as: .\" .RS .\" alias pssh_servers="pssh -h /path/to/server_list.txt -l root -A" .\" .RE .PP The ssh_config file can include an arbitrary number of Host sections. Each host entry specifies ssh options which apply only to the given host. Host definitions can even behave like aliases if the HostName option is included. This ssh feature, in combination with pssh host files, provides a tremendous amount of flexibility. .PP Internally uses the .B pkill command and sends signal 9 (the unblockable KILL signal). .SH EXIT STATUS .PP The exit status codes from pnuke are as follows: .TP .B 0 Success .TP .B 1 Miscellaneous error .TP .B 2 Syntax or usage error .TP .B 3 At least one process was killed by a signal or timed out. .TP .B 4 All processes completed, but at least one ssh process reported an error (exit status 255). .TP .B 5 There were no ssh errors, but at least one remote command had a non-zero exit status. .SH AUTHORS .PP Written by Brent N. Chun and Andrew McNabb . https://github.com/lilydjwg/pssh .SH SEE ALSO .BR ssh (1), .BR ssh_config(5), .BR pssh (1), .BR pscp (1), .BR prsync (1), .BR pslurp (1), pssh-2.3.4/man/man1/prsync.1000066400000000000000000000134111364227332400155120ustar00rootroot00000000000000.\" Man page for prsync. See "man 7 man" and "man man-pages" for formatting info. .TH prsync 1 "January 24, 2012" .SH NAME prsync \(em parallel file sync program .SH SYNOPSIS .B prsync .RB [ \-vAraz ] .RB [ \-h .IR hosts_file ] .RB [ \-H .RI [ user @] host [: port ]] .RB [ \-l .IR user ] .RB [ \-p .IR par ] .RB [ \-o .IR outdir ] .RB [ \-e .IR errdir ] .RB [ \-t .IR timeout ] .RB [ \-O .IR options ] .RB [ \-x .IR args ] .RB [ \-X .IR arg ] .RB [ \-S .IR args ] .I local ... .I remote .SH DESCRIPTION .PP .B prsync is a program for copying files in parallel to a number of hosts using the popular .B rsync program. It provides features such as passing a password to ssh, saving output to files, and timing out. .SH OPTIONS .TP .BI \-h " host_file" .PD 0 .TP .BI \-\-hosts " host_file" Read hosts from the given .IR host_file . Lines in the host file are of the form .RI [ user @] host [: port ] and can include blank lines and comments (lines beginning with "#"). If multiple host files are given (the .B \-h option is used more than once), then prsync behaves as though these files were concatenated together. If a host is specified multiple times, then prsync will connect the given number of times. .TP .B \-H .RI [ user @] host [: port ] .PD 0 .TP .B \-\-host .RI [ user @] host [: port ] .PD 0 .TP .B \-H .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .TP .B \-\-host .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .IP Add the given host strings to the list of hosts. This option may be given multiple times, and may be used in conjunction with the .B \-h option. .TP .BI \-l " user" .PD 0 .TP .BI \-\-user " user" Use the given username as the default for any host entries that don't specifically specify a user. .TP .BI \-p " parallelism" .PD 0 .TP .BI \-\-par " parallelism" Use the given number as the maximum number of concurrent connections. .TP .BI \-t " timeout" .PD 0 .TP .BI \-\-timeout " timeout" Make connections time out after the given number of seconds. With a value of 0, prsync will not timeout any connections. .TP .BI \-o " outdir" .PD 0 .TP .BI \-\-outdir " outdir" Save standard output to files in the given directory. Filenames are of the form .RI [ user @] host [: port ][. num ] where the user and port are only included for hosts that explicitly specify them. The number is a counter that is incremented each time for hosts that are specified more than once. .TP .BI \-e " errdir" .PD 0 .TP .BI \-\-errdir " errdir" Save standard error to files in the given directory. Filenames are of the same form as with the .B \-o option. .TP .BI \-x " args" .PD 0 .TP .BI \-\-extra-args " args" Passes extra rsync command-line arguments (see the .BR rsync (1) man page for more information about rsync arguments). This option may be specified multiple times. The arguments are processed to split on whitespace, protect text within quotes, and escape with backslashes. To pass arguments without such processing, use the .B \-X option instead. .TP .BI \-X " arg" .PD 0 .TP .BI \-\-extra-arg " arg" Passes a single rsync command-line argument (see the .BR rsync (1) man page for more information about rsync arguments). Unlike the .B \-x option, no processing is performed on the argument, including word splitting. To pass multiple command-line arguments, use the option once for each argument. .TP .BI \-O " options" .PD 0 .TP .BI \-\-options " options" SSH options in the format used in the SSH configuration file (see the .BR ssh_config (5) man page for more information). This option may be specified multiple times. .TP .B \-A .PD 0 .TP .B \-\-askpass Prompt for a password and pass it to ssh. The password may be used for either to unlock a key or for password authentication. The password is transferred in a fairly secure manner (e.g., it will not show up in argument lists). However, be aware that a root user on your system could potentially intercept the password. .TP .B \-v .PD 0 .TP .B \-\-verbose Include error messages from rsync with the .B \-i and .B \e options. .TP .B \-r .PD 0 .TP .B \-\-recursive Recursively copy directories. .TP .B \-a .PD 0 .TP .B \-\-archive Use rsync archive mode (rsync's \-a option). .TP .B \-z .PD 0 .TP .B \-\-compress Use rsync compression. .TP .BI \-S " args" .PD 0 .TP .BI \-\-ssh-args " args" Passes extra SSH command-line arguments (see the .BR ssh (1) man page for more information about SSH arguments). The given value is appended to the ssh command (rsync's \-e option) without any processing. .\" .SH EXAMPLES .\" .PP .\" Connect to host1 and host2, and print "hello, world" from each: .\" .RS .\" pssh -i -H "host1 host2" echo "hello, world" .\" .RE .SH TIPS .\" .PP .\" If you have a set of hosts that you connect to frequently with specific .\" options, it may be helpful to create an alias such as: .\" .RS .\" alias pssh_servers="pssh -h /path/to/server_list.txt -l root -A" .\" .RE .PP The ssh_config file can include an arbitrary number of Host sections. Each host entry specifies ssh options which apply only to the given host. Host definitions can even behave like aliases if the HostName option is included. This ssh feature, in combination with pssh host files, provides a tremendous amount of flexibility. .SH EXIT STATUS .PP The exit status codes from prsync are as follows: .TP .B 0 Success .TP .B 1 Miscellaneous error .TP .B 2 Syntax or usage error .TP .B 3 At least one process was killed by a signal or timed out. .TP .B 4 All processes completed, but at least one rsync process reported an error (exit status other than 0). .SH AUTHORS .PP Written by Brent N. Chun and Andrew McNabb . https://github.com/lilydjwg/pssh .SH SEE ALSO .BR rsync (1), .BR ssh (1), .BR ssh_config(5), .BR pssh (1), .BR prsync (1), .BR pslurp (1), .BR pnuke (1), pssh-2.3.4/man/man1/pscp.1000066400000000000000000000124411364227332400151430ustar00rootroot00000000000000.\" Man page for pscp. See "man 7 man" and "man man-pages" for formatting info. .TH pscp 1 "January 24, 2012" .SH NAME pscp \(em parallel file upload program .SH SYNOPSIS .B pscp .RB [ \-vAr ] .RB [ \-h .IR hosts_file ] .RB [ \-H .RI [ user @] host [: port ]] .RB [ \-l .IR user ] .RB [ \-p .IR par ] .RB [ \-o .IR outdir ] .RB [ \-e .IR errdir ] .RB [ \-t .IR timeout ] .RB [ \-O .IR options ] .RB [ \-x .IR args ] .RB [ \-X .IR arg ] .I local .I remote .SH DESCRIPTION .PP .B pscp is a program for copying files in parallel to a number of hosts using the .B scp program. It provides features such as passing a password to scp, saving output to files, and timing out. .SH OPTIONS .TP .BI \-h " host_file" .PD 0 .TP .BI \-\-hosts " host_file" Read hosts from the given .IR host_file . Lines in the host file are of the form .RI [ user @] host [: port ] and can include blank lines and comments (lines beginning with "#"). If multiple host files are given (the .B \-h option is used more than once), then pscp behaves as though these files were concatenated together. If a host is specified multiple times, then pscp will connect the given number of times. .TP .B \-H .RI [ user @] host [: port ] .PD 0 .TP .B \-\-host .RI [ user @] host [: port ] .PD 0 .TP .B \-H .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .TP .B \-\-host .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .IP Add the given host strings to the list of hosts. This option may be given multiple times, and may be used in conjunction with the .B \-h option. .TP .BI \-l " user" .PD 0 .TP .BI \-\-user " user" Use the given username as the default for any host entries that don't specifically specify a user. .TP .BI \-p " parallelism" .PD 0 .TP .BI \-\-par " parallelism" Use the given number as the maximum number of concurrent connections. .TP .BI \-t " timeout" .PD 0 .TP .BI \-\-timeout " timeout" Make connections time out after the given number of seconds. With a value of 0, pscp will not timeout any connections. .TP .BI \-o " outdir" .PD 0 .TP .BI \-\-outdir " outdir" Save standard output to files in the given directory. Filenames are of the form .RI [ user @] host [: port ][. num ] where the user and port are only included for hosts that explicitly specify them. The number is a counter that is incremented each time for hosts that are specified more than once. .TP .BI \-e " errdir" .PD 0 .TP .BI \-\-errdir " errdir" Save standard error to files in the given directory. Filenames are of the same form as with the .B \-o option. .TP .BI \-x " args" .PD 0 .TP .BI \-\-extra-args " args" Passes extra SSH command-line arguments (see the .BR ssh (1) man page for more information about SSH arguments). This option may be specified multiple times. The arguments are processed to split on whitespace, protect text within quotes, and escape with backslashes. To pass arguments without such processing, use the .B \-X option instead. .TP .BI \-X " arg" .PD 0 .TP .BI \-\-extra-arg " arg" Passes a single SSH command-line argument (see the .BR ssh (1) man page for more information about SSH arguments). Unlike the .B \-x option, no processing is performed on the argument, including word splitting. To pass multiple command-line arguments, use the option once for each argument. .TP .BI \-O " options" .PD 0 .TP .BI \-\-options " options" SSH options in the format used in the SSH configuration file (see the .BR ssh_config (5) man page for more information). This option may be specified multiple times. .TP .B \-A .PD 0 .TP .B \-\-askpass Prompt for a password and pass it to ssh. The password may be used for either to unlock a key or for password authentication. The password is transferred in a fairly secure manner (e.g., it will not show up in argument lists). However, be aware that a root user on your system could potentially intercept the password. .TP .B \-v .PD 0 .TP .B \-\-verbose Include error messages from ssh with the .B \-i and .B \e options. .TP .B \-r .PD 0 .TP .B \-\-recursive Recursively copy directories. .\" .SH EXAMPLES .\" .PP .\" Connect to host1 and host2, and print "hello, world" from each: .\" .RS .\" pssh -i -H "host1 host2" echo "hello, world" .\" .RE .SH TIPS .\" .PP .\" If you have a set of hosts that you connect to frequently with specific .\" options, it may be helpful to create an alias such as: .\" .RS .\" alias pssh_servers="pssh -h /path/to/server_list.txt -l root -A" .\" .RE .PP The ssh_config file can include an arbitrary number of Host sections. Each host entry specifies ssh options which apply only to the given host. Host definitions can even behave like aliases if the HostName option is included. This ssh feature, in combination with pssh host files, provides a tremendous amount of flexibility. .SH EXIT STATUS .PP The exit status codes from pscp are as follows: .TP .B 0 Success .TP .B 1 Miscellaneous error .TP .B 2 Syntax or usage error .TP .B 3 At least one process was killed by a signal or timed out. .TP .B 4 All processes completed, but at least one scp process reported an error (exit status other than 0). .SH AUTHORS .PP Written by Brent N. Chun and Andrew McNabb . https://github.com/lilydjwg/pssh .SH SEE ALSO .BR ssh (1), .BR ssh_config(5), .BR pssh (1), .BR prsync (1), .BR pslurp (1), .BR pnuke (1), pssh-2.3.4/man/man1/pslurp.1000066400000000000000000000127141364227332400155260ustar00rootroot00000000000000.\" Man page for pslurp. See "man 7 man" and "man man-pages" for formatting info. .TH pslurp 1 "January 24, 2012" .SH NAME pslurp \(em parallel file download program .SH SYNOPSIS .B pslurp .RB [ \-vAr ] .RB [ \-h .IR hosts_file ] .RB [ \-H .RI [ user @] host [: port ]] .RB [ \-l .IR user ] .RB [ \-p .IR par ] .RB [ \-o .IR outdir ] .RB [ \-e .IR errdir ] .RB [ \-t .IR timeout ] .RB [ \-O .IR options ] .RB [ \-x .IR args ] .RB [ \-X .IR arg ] .RB [ \-L .IR localdir ] .I remote .I local .SH DESCRIPTION .PP .B pslurp is a program for copying files in parallel from a number of hosts using the .B scp program. It provides features such as passing a password to scp, saving output to files, and timing out. .SH OPTIONS .TP .BI \-h " host_file" .PD 0 .TP .BI \-\-hosts " host_file" Read hosts from the given .IR host_file . Lines in the host file are of the form .RI [ user @] host [: port ] and can include blank lines and comments (lines beginning with "#"). If multiple host files are given (the .B \-h option is used more than once), then pslurp behaves as though these files were concatenated together. If a host is specified multiple times, then pslurp will connect the given number of times. .TP .B \-H .RI [ user @] host [: port ] .PD 0 .TP .B \-\-host .RI [ user @] host [: port ] .PD 0 .TP .B \-H .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .TP .B \-\-host .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .IP Add the given host strings to the list of hosts. This option may be given multiple times, and may be used in conjunction with the .B \-h option. .TP .BI \-l " user" .PD 0 .TP .BI \-\-user " user" Use the given username as the default for any host entries that don't specifically specify a user. .TP .BI \-p " parallelism" .PD 0 .TP .BI \-\-par " parallelism" Use the given number as the maximum number of concurrent connections. .TP .BI \-t " timeout" .PD 0 .TP .BI \-\-timeout " timeout" Make connections time out after the given number of seconds. With a value of 0, pslurp will not timeout any connections. .TP .BI \-o " outdir" .PD 0 .TP .BI \-\-outdir " outdir" Save standard output to files in the given directory. Filenames are of the form .RI [ user @] host [: port ][. num ] where the user and port are only included for hosts that explicitly specify them. The number is a counter that is incremented each time for hosts that are specified more than once. .TP .BI \-e " errdir" .PD 0 .TP .BI \-\-errdir " errdir" Save standard error to files in the given directory. Filenames are of the same form as with the .B \-o option. .TP .BI \-x " args" .PD 0 .TP .BI \-\-extra-args " args" Passes extra SSH command-line arguments (see the .BR ssh (1) man page for more information about SSH arguments). This option may be specified multiple times. The arguments are processed to split on whitespace, protect text within quotes, and escape with backslashes. To pass arguments without such processing, use the .B \-X option instead. .TP .BI \-X " arg" .PD 0 .TP .BI \-\-extra-arg " arg" Passes a single SSH command-line argument (see the .BR ssh (1) man page for more information about SSH arguments). Unlike the .B \-x option, no processing is performed on the argument, including word splitting. To pass multiple command-line arguments, use the option once for each argument. .TP .BI \-O " options" .PD 0 .TP .BI \-\-options " options" SSH options in the format used in the SSH configuration file (see the .BR ssh_config (5) man page for more information). This option may be specified multiple times. .TP .B \-A .PD 0 .TP .B \-\-askpass Prompt for a password and pass it to ssh. The password may be used for either to unlock a key or for password authentication. The password is transferred in a fairly secure manner (e.g., it will not show up in argument lists). However, be aware that a root user on your system could potentially intercept the password. .TP .B \-v .PD 0 .TP .B \-\-verbose Include error messages from ssh with the .B \-i and .B \e options. .TP .B \-r .PD 0 .TP .B \-\-recursive Recursively copy directories. .TP .BI \-L " localdir" .PD 0 .TP .BI \-\-localdir " localdir" Copy files from the remote host to the given local directory. .\" .SH EXAMPLES .\" .PP .\" Connect to host1 and host2, and print "hello, world" from each: .\" .RS .\" pssh -i -H "host1 host2" echo "hello, world" .\" .RE .SH TIPS .\" .PP .\" If you have a set of hosts that you connect to frequently with specific .\" options, it may be helpful to create an alias such as: .\" .RS .\" alias pssh_servers="pssh -h /path/to/server_list.txt -l root -A" .\" .RE .PP The ssh_config file can include an arbitrary number of Host sections. Each host entry specifies ssh options which apply only to the given host. Host definitions can even behave like aliases if the HostName option is included. This ssh feature, in combination with pssh host files, provides a tremendous amount of flexibility. .SH EXIT STATUS .PP The exit status codes from pslurp are as follows: .TP .B 0 Success .TP .B 1 Miscellaneous error .TP .B 2 Syntax or usage error .TP .B 3 At least one process was killed by a signal or timed out. .TP .B 4 All processes completed, but at least one scp process reported an error (exit status other than 0). .SH AUTHORS .PP Written by Brent N. Chun and Andrew McNabb . https://github.com/lilydjwg/pssh .SH SEE ALSO .BR ssh (1), .BR ssh_config(5), .BR pssh (1), .BR pscp (1), .BR prsync (1), .BR pnuke (1), pssh-2.3.4/man/man1/pssh.1000066400000000000000000000211371364227332400151550ustar00rootroot00000000000000.\" Man page for pssh. See "man 7 man" and "man man-pages" for formatting info. .TH pssh 1 "January 24, 2012" .SH NAME pssh \(em parallel ssh program .SH SYNOPSIS .B pssh .RB [ \-vAiIP ] .RB [ \-h .IR hosts_file ] .RB [ \-H .RI [ user @] host [: port ]] .RB [ \-g .IR pattern ] .RB [ \-l .IR user ] .RB [ \-p .IR par ] .RB [ \-o .IR outdir ] .RB [ \-e .IR errdir ] .RB [ \-t .IR timeout ] .RB [ \-O .IR options ] .RB [ \-x .IR args ] .RB [ \-X .IR arg ] .I command ... .B pssh \-I .RB [ \-vAiIP ] .RB [ \-h .IR hosts_file ] .RB [ \-H .RI [ user @] host [: port ]] .RB [ \-g .IR pattern ] .RB [ \-l .IR user ] .RB [ \-p .IR par ] .RB [ \-o .IR outdir ] .RB [ \-e .IR errdir ] .RB [ \-t .IR timeout ] .RB [ \-O .IR options ] .RB [ \-x .IR args ] .RB [ \-X .IR arg ] .RI [ command .IR ... ] .SH DESCRIPTION .PP .B pssh is a program for executing ssh in parallel on a number of hosts. It provides features such as sending input to all of the processes, passing a password to ssh, saving output to files, and timing out. The PSSH_NODENUM, PSSH_NUMNODES, PSSH_HOST environment variables are sent to the remote host. The PSSH_NODENUM variable is assigned a unique number for each ssh connection, starting with 0 and counting up. The PSSH_NUMNODES variable is assigned the total number of node being used. The PSSH_HOST variable is assigned the name of the host as specified in the hosts list. Note that sshd drops environment variables by default, so sshd_config on the remote host must include the line: .RS AcceptEnv PSSH_NODENUM PSSH_NUMNODES PSSH_HOST .RE .SH OPTIONS .TP .BI \-h " host_file" .PD 0 .TP .BI \-\-hosts " host_file" Read hosts from the given .IR host_file . Lines in the host file are of the form .RI [ user @] host [: port ] and can include blank lines and comments (lines beginning with "#"). If multiple host files are given (the .B \-h option is used more than once), then pssh behaves as though these files were concatenated together. If a host is specified multiple times, then pssh will connect the given number of times. .TP .B \-H .RI [ user @] host [: port ] .PD 0 .TP .B \-\-host .RI [ user @] host [: port ] .PD 0 .TP .B \-H .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .TP .B \-\-host .RI \(dq[ user @] host [: port ] [ .RI [ user @] host [: port ] ... ]\(dq .PD 0 .IP Add the given host strings to the list of hosts. This option may be given multiple times, and may be used in conjunction with the .B \-h option. .TP .BI \-g " pattern" .PD 0 .TP .BI \-\-host\-glob " pattern" Filter hosts with glob pattern .IR pattern . This uses the same syntax as shell globs. Make sure to quote the pattern to prevent shell from expanding it. Examples are "*web*" and "company_*". .TP .BI \-l " user" .PD 0 .TP .BI \-\-user " user" Use the given username as the default for any host entries that don't specifically specify a user. .TP .BI \-p " parallelism" .PD 0 .TP .BI \-\-par " parallelism" Use the given number as the maximum number of concurrent connections. .TP .BI \-t " timeout" .PD 0 .TP .BI \-\-timeout " timeout" Make connections time out after the given number of seconds. With a value of 0, pssh will not timeout any connections. .TP .BI \-o " outdir" .PD 0 .TP .BI \-\-outdir " outdir" Save standard output to files in the given directory. Filenames are of the form .RI [ user @] host [: port ][. num ] where the user and port are only included for hosts that explicitly specify them. The number is a counter that is incremented each time for hosts that are specified more than once. .TP .BI \-e " errdir" .PD 0 .TP .BI \-\-errdir " errdir" Save standard error to files in the given directory. Filenames are of the same form as with the .B \-o option. .TP .BI \-x " args" .PD 0 .TP .BI \-\-extra-args " args" Passes extra SSH command-line arguments (see the .BR ssh (1) man page for more information about SSH arguments). This option may be specified multiple times. The arguments are processed to split on whitespace, protect text within quotes, and escape with backslashes. To pass arguments without such processing, use the .B \-X option instead. .TP .BI \-X " arg" .PD 0 .TP .BI \-\-extra-arg " arg" Passes a single SSH command-line argument (see the .BR ssh (1) man page for more information about SSH arguments). Unlike the .B \-x option, no processing is performed on the argument, including word splitting. To pass multiple command-line arguments, use the option once for each argument. .TP .BI \-O " options" .PD 0 .TP .BI \-\-options " options" SSH options in the format used in the SSH configuration file (see the .BR ssh_config (5) man page for more information). This option may be specified multiple times. .TP .B \-A .PD 0 .TP .B \-\-askpass Prompt for a password and pass it to ssh. The password may be used for either to unlock a key or for password authentication. The password is transferred in a fairly secure manner (e.g., it will not show up in argument lists). However, be aware that a root user on your system could potentially intercept the password. .TP .B \-i .PD 0 .TP .B \-\-inline Display standard output and standard error as each host completes. .TP .B \-\-inline\-stdout Display standard output (but not standard error) as each host completes. .TP .B \-v .PD 0 .TP .B \-\-verbose Include error messages from ssh with the .B \-i and .B \e options. .TP .B \-I .PD 0 .TP .B \-\-send-input Read input and send to each ssh process. Since ssh allows a command script to be sent on standard input, the .B \-I option may be used in lieu of the command argument. .TP .B \-P .PD 0 .TP .B \-\-print Display output as it arrives. This option is of limited usefulness because output from different hosts are interleaved. .SH EXAMPLES .PP Connect to host1 and host2, and print "hello, world" from each: .RS pssh -i -H "host1 host2" echo "hello, world" .RE .PP Print "hello, world" from each host specified in the file hosts.txt: .RS pssh -i -h hosts.txt echo "hello, world" .RE .PP Run a command as root with a prompt for the root password: .RS pssh -i -h hosts.txt -A -l root echo hi .RE .PP Run a long command without timing out: .RS pssh -i -h hosts.txt -t 0 sleep 10000 .RE .PP If the file hosts.txt has a large number of entries, say 100, then the parallelism option may also be set to 100 to ensure that the commands are run concurrently: .RS pssh -i -h hosts.txt -p 100 -t 0 sleep 10000 .RE .PP Run a command without checking or saving host keys: .RS pssh -i -H host1 -H host2 -x "-O StrictHostKeyChecking=no -O UserKnownHostsFile=/dev/null -O GlobalKnownHostsFile=/dev/null" echo hi .RE .PP Print the node number for each connection (this will print 0, 1, and 2): .RS pssh -i -H host1 -H host1 -H host2 'echo $PSSH_NODENUM' .RE .SH TIPS .PP If you have a set of hosts that you connect to frequently with specific options, it may be helpful to create an alias such as: .RS alias pssh_servers="pssh -h /path/to/server_list.txt -l root -A" .RE .PP Note that when an ssh command is terminated, it does not kill remote processes (OpenSSH bug #396 has been open since 2002). One workaround is to instruct ssh to allocate a pseudo-terminal, which makes it behave more like a normal interactive ssh session. To do this, use pssh's "-x" option to pass "-tt" to ssh. For example: .RS pssh -i -x "-tt" -h hosts.txt -t 10 sleep 1000 .RE will ensure that all of the sleep commands will terminate (with SIGHUP) after the 10 second timeout. .PP By default, ssh uses full buffering for non-interactive commands. Line buffering may be preferrable to full buffering if you intend to look at the files in an output directory as a command is running. To switch ssh to use line buffering, use its "-tt" option (which allocates a pseudo-terminal) using the "-x" option in pssh. .PP The ssh_config file can include an arbitrary number of Host sections. Each host entry specifies ssh options which apply only to the given host. Host definitions can even behave like aliases if the HostName option is included. This ssh feature, in combination with pssh host files, provides a tremendous amount of flexibility. .SH EXIT STATUS .PP The exit status codes from pssh are as follows: .TP .B 0 Success .TP .B 1 Miscellaneous error .TP .B 2 Syntax or usage error .TP .B 3 At least one process was killed by a signal or timed out. .TP .B 4 All processes completed, but at least one ssh process reported an error (exit status 255). .TP .B 5 There were no ssh errors, but at least one remote command had a non-zero exit status. .SH AUTHORS .PP Written by Brent N. Chun and Andrew McNabb . https://github.com/lilydjwg/pssh .SH SEE ALSO .BR ssh (1), .BR ssh_config (5), .BR pscp (1), .BR prsync (1), .BR pslurp (1), .BR pnuke (1), pssh-2.3.4/psshlib/000077500000000000000000000000001364227332400141475ustar00rootroot00000000000000pssh-2.3.4/psshlib/__init__.py000066400000000000000000000001601364227332400162550ustar00rootroot00000000000000from .pardo import pardo, prange, penumerate, pproduct __all__ = ['pardo', 'prange', 'penumerate', 'pproduct'] pssh-2.3.4/psshlib/askpass_client.py000066400000000000000000000067051364227332400175340ustar00rootroot00000000000000#!/usr/bin/env python # -*- Mode: python -*- # Copyright (c) 2009-2012, Andrew McNabb """Implementation of SSH_ASKPASS to get a password to ssh from pssh. The password is read from the socket specified by the environment variable PSSH_ASKPASS_SOCKET. The other end of this socket is pssh. The ssh man page discusses SSH_ASKPASS as follows: If ssh needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If ssh does not have a terminal associated with it but DISPLAY and SSH_ASKPASS are set, it will execute the program specified by SSH_ASKPASS and open an X11 window to read the passphrase. This is particularly useful when calling ssh from a .xsession or related script. (Note that on some machines it may be necessary to redirect the input from /dev/null to make this work.) """ import os import socket import sys import textwrap bin_dir = os.path.dirname(os.path.abspath(sys.argv[0])) askpass_bin_path = os.path.join(bin_dir, 'pssh-askpass') ASKPASS_PATHS = (askpass_bin_path, '/usr/libexec/pssh/pssh-askpass', '/usr/local/libexec/pssh/pssh-askpass', '/usr/lib/pssh/pssh-askpass', '/usr/local/lib/pssh/pssh-askpass') _executable_path = None def executable_path(): """Determines the value to use for SSH_ASKPASS. The value is cached since this may be called many times. """ global _executable_path if _executable_path is None: for path in ASKPASS_PATHS: if os.access(path, os.X_OK): _executable_path = path break else: _executable_path = '' sys.stderr.write(textwrap.fill("Warning: could not find an" " executable path for askpass because PSSH was not" " installed correctly. Password prompts will not work.")) sys.stderr.write('\n') return _executable_path def askpass_main(): """Connects to pssh over the socket specified at PSSH_ASKPASS_SOCKET.""" verbose = os.getenv('PSSH_ASKPASS_VERBOSE') # It's not documented anywhere, as far as I can tell, but ssh may prompt # for a password or ask a yes/no question. The command-line argument # specifies what is needed. if len(sys.argv) > 1: prompt = sys.argv[1] if verbose: sys.stderr.write('pssh-askpass received prompt: "%s"\n' % prompt) if not (prompt.strip().lower().endswith('password:') or 'enter passphrase for key' in prompt.strip().lower()): sys.stderr.write(prompt) sys.stderr.write('\n') sys.exit(1) else: sys.stderr.write('Error: pssh-askpass called without a prompt.\n') sys.exit(1) address = os.getenv('PSSH_ASKPASS_SOCKET') if not address: sys.stderr.write(textwrap.fill("pssh error: SSH requested a password." " Please create SSH keys or use the -A option to provide a" " password.")) sys.stderr.write('\n') sys.exit(1) sock = socket.socket(socket.AF_UNIX) try: sock.connect(address) except socket.error: _, e, _ = sys.exc_info() message = e.args[1] sys.stderr.write("Couldn't bind to %s: %s.\n" % (address, message)) sys.exit(2) try: password = sock.makefile().read() except socket.error: sys.stderr.write("Socket error.\n") sys.exit(3) print(password) if __name__ == '__main__': askpass_main() pssh-2.3.4/psshlib/askpass_server.py000066400000000000000000000056321364227332400175620ustar00rootroot00000000000000#!/usr/bin/env python # -*- Mode: python -*- # Copyright (c) 2009-2012, Andrew McNabb """Sends the password over a socket to askpass. """ import errno import getpass import os import socket import sys import tempfile import textwrap from psshlib import psshutil class PasswordServer(object): """Listens on a UNIX domain socket for password requests.""" def __init__(self): self.sock = None self.tempdir = None self.address = None self.socketmap = {} self.buffermap = {} def start(self, iomap, backlog): """Prompts for the password, creates a socket, and starts listening. The specified backlog should be the max number of clients connecting at once. """ message = ('Warning: do not enter your password if anyone else has' ' superuser privileges or access to your account.') print(textwrap.fill(message)) self.password = getpass.getpass() # Note that according to the docs for mkdtemp, "The directory is # readable, writable, and searchable only by the creating user." self.tempdir = tempfile.mkdtemp(prefix='pssh.') self.address = os.path.join(self.tempdir, 'pssh_askpass_socket') self.sock = socket.socket(socket.AF_UNIX) psshutil.set_cloexec(self.sock) self.sock.bind(self.address) self.sock.listen(backlog) iomap.register_read(self.sock.fileno(), self.handle_listen) def handle_listen(self, fd, iomap): try: conn = self.sock.accept()[0] except socket.error: _, e, _ = sys.exc_info() number = e.args[0] if number == errno.EINTR: return else: # TODO: print an error message here? self.sock.close() self.sock = None fd = conn.fileno() iomap.register_write(fd, self.handle_write) self.socketmap[fd] = conn self.buffermap[fd] = self.password def handle_write(self, fd, iomap): buffer = self.buffermap[fd] conn = self.socketmap[fd] try: bytes_written = conn.send(buffer.encode()) except socket.error: _, e, _ = sys.exc_info() number = e.args[0] if number == errno.EINTR: return else: self.close_socket(fd, iomap) buffer = buffer[bytes_written:] if buffer: self.buffermap[fd] = buffer else: self.close_socket(fd, iomap) def close_socket(self, fd, iomap): iomap.unregister(fd) self.socketmap[fd].close() del self.socketmap[fd] del self.buffermap[fd] def __del__(self): if self.sock: self.sock.close() self.sock = None if self.address: os.remove(self.address) if self.tempdir: os.rmdir(self.tempdir) pssh-2.3.4/psshlib/cli.py000066400000000000000000000106301364227332400152700ustar00rootroot00000000000000# Copyright (c) 2009-2012, Andrew McNabb # Copyright (c) 2003-2008, Brent N. Chun import optparse import os import shlex import sys import textwrap from psshlib import version _DEFAULT_PARALLELISM = 32 _DEFAULT_TIMEOUT = 0 # "infinity" by default def common_parser(): """ Create a basic OptionParser with arguments common to all pssh programs. """ # The "resolve" conflict handler avoids errors from the hosts option # conflicting with the help option. parser = optparse.OptionParser(conflict_handler='resolve', version=version.VERSION) # Ensure that options appearing after the command are sent to ssh. parser.disable_interspersed_args() parser.epilog = "Example: pssh -h nodes.txt -l irb2 -o /tmp/foo uptime" parser.add_option('-h', '--hosts', dest='host_files', action='append', metavar='HOST_FILE', help='hosts file (each line "[user@]host[:port]")') parser.add_option('-H', '--host', dest='host_strings', action='append', metavar='HOST_STRING', help='additional host entries ("[user@]host[:port]")') parser.add_option('-l', '--user', dest='user', help='username (OPTIONAL)') parser.add_option('-p', '--par', dest='par', type='int', help='max number of parallel threads (OPTIONAL)') parser.add_option('-o', '--outdir', dest='outdir', help='output directory for stdout files (OPTIONAL)') parser.add_option('-e', '--errdir', dest='errdir', help='output directory for stderr files (OPTIONAL)') parser.add_option('-t', '--timeout', dest='timeout', type='int', help='timeout (secs) (0 = no timeout) per host (OPTIONAL)') parser.add_option('-O', '--option', dest='options', action='append', metavar='OPTION', help='SSH option (OPTIONAL)') parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='turn on warning and diagnostic messages (OPTIONAL)') parser.add_option('-A', '--askpass', dest='askpass', action='store_true', help='Ask for a password (OPTIONAL)') parser.add_option('-x', '--extra-args', action='callback', type='string', metavar='ARGS', callback=shlex_append, dest='extra', help='Extra command-line arguments, with processing for ' 'spaces, quotes, and backslashes') parser.add_option('-X', '--extra-arg', dest='extra', action='append', metavar='ARG', help='Extra command-line argument') parser.add_option('-g', '--host-glob', dest='host_glob', type='string', help='Shell-style glob to filter hosts (OPTIONAL)') return parser def common_defaults(**kwargs): defaults = dict(par=_DEFAULT_PARALLELISM, timeout=_DEFAULT_TIMEOUT) defaults.update(**kwargs) envvars = [('user', 'PSSH_USER'), ('par', 'PSSH_PAR'), ('outdir', 'PSSH_OUTDIR'), ('errdir', 'PSSH_ERRDIR'), ('timeout', 'PSSH_TIMEOUT'), ('verbose', 'PSSH_VERBOSE'), ('print_out', 'PSSH_PRINT'), ('askpass', 'PSSH_ASKPASS'), ('inline', 'PSSH_INLINE'), ('recursive', 'PSSH_RECURSIVE'), ('archive', 'PSSH_ARCHIVE'), ('compress', 'PSSH_COMPRESS'), ('localdir', 'PSSH_LOCALDIR'), ] for option, var, in envvars: value = os.getenv(var) if value: defaults[option] = value value = os.getenv('PSSH_OPTIONS') if value: defaults['options'] = [value] value = os.getenv('PSSH_HOSTS') if value: message1 = ('Warning: the PSSH_HOSTS environment variable is ' 'deprecated. Please use the "-h" option instead, and consider ' 'creating aliases for convenience. For example:') message2 = " alias pssh_abc='pssh -h /path/to/hosts_abc'" sys.stderr.write(textwrap.fill(message1)) sys.stderr.write('\n') sys.stderr.write(message2) sys.stderr.write('\n') defaults['host_files'] = [value] return defaults def shlex_append(option, opt_str, value, parser): """An optparse callback similar to the append action. The given value is processed with shlex, and the resulting list is concatenated to the option's dest list. """ lst = getattr(parser.values, option.dest) if lst is None: lst = [] setattr(parser.values, option.dest, lst) lst.extend(shlex.split(value)) pssh-2.3.4/psshlib/color.py000066400000000000000000000025101364227332400156350ustar00rootroot00000000000000# Copyright (c) 2009-2012, Andrew McNabb # Copyright (c) 2003-2008, Brent N. Chun def with_color(string, fg, bg=49): '''Given foreground/background ANSI color codes, return a string that, when printed, will format the supplied string using the supplied colors. ''' return "\x1b[%dm\x1b[%dm%s\x1b[39m\x1b[49m" % (fg, bg, string) def B(string): '''Returns a string that, when printed, will display the supplied string in ANSI bold. ''' return "\x1b[1m%s\x1b[22m" % string def r(string): return with_color(string, 31) # Red def g(string): return with_color(string, 32) # Green def y(string): return with_color(string, 33) # Yellow def b(string): return with_color(string, 34) # Blue def m(string): return with_color(string, 35) # Magenta def c(string): return with_color(string, 36) # Cyan def w(string): return with_color(string, 37) # White #following from Python cookbook, #475186 def has_colors(stream): '''Returns boolean indicating whether or not the supplied stream supports ANSI color. ''' if not hasattr(stream, "isatty"): return False if not stream.isatty(): return False # auto color only on TTYs try: import curses curses.setupterm() return curses.tigetnum("colors") > 2 except: # guess false in case of error return False pssh-2.3.4/psshlib/manager.py000066400000000000000000000315221364227332400161360ustar00rootroot00000000000000# Copyright (c) 2009-2012, Andrew McNabb from errno import EINTR import os import fcntl import select import signal import sys import threading try: import queue except ImportError: import Queue as queue from psshlib.askpass_server import PasswordServer from psshlib import psshutil READ_SIZE = 1 << 16 class FatalError(RuntimeError): """A fatal error in the PSSH Manager.""" pass class Manager(object): """Executes tasks concurrently. Tasks are added with add_task() and executed in parallel with run(). Returns a list of the exit statuses of the processes. Arguments: limit: Maximum number of commands running at once. timeout: Maximum allowed execution time in seconds. """ def __init__(self, opts): self.limit = opts.par self.timeout = opts.timeout self.askpass = opts.askpass self.outdir = opts.outdir self.errdir = opts.errdir self.iomap = make_iomap() self.next_nodenum = 0 self.numnodes = 0 self.tasks = [] self.running = [] self.done = [] self.askpass_socket = None def run(self): """Processes tasks previously added with add_task.""" try: if self.outdir or self.errdir: writer = Writer(self.outdir, self.errdir) writer.start() else: writer = None if self.askpass: pass_server = PasswordServer() pass_server.start(self.iomap, self.limit) self.askpass_socket = pass_server.address self.set_sigchld_handler() try: self.update_tasks(writer) wait = None while self.running or self.tasks: # Opt for efficiency over subsecond timeout accuracy. if wait is None or wait < 1: wait = 1 self.iomap.poll(wait) self.update_tasks(writer) wait = self.check_timeout() except KeyboardInterrupt: # This exception handler tries to clean things up and prints # out a nice status message for each interrupted host. self.interrupted() except KeyboardInterrupt: # This exception handler doesn't print out any fancy status # information--it just stops. pass if writer: writer.signal_quit() writer.join() statuses = [task.exitstatus for task in self.done] return statuses def clear_sigchld_handler(self): signal.signal(signal.SIGCHLD, signal.SIG_DFL) def set_sigchld_handler(self): signal.signal(signal.SIGCHLD, self.handle_sigchld) # This should keep reads and writes from getting EINTR. if hasattr(signal, 'siginterrupt'): signal.siginterrupt(signal.SIGCHLD, False) def handle_sigchld(self, number, frame): """Apparently we need a sigchld handler to make set_wakeup_fd work.""" for task in self.running: if task.proc: task.proc.poll() # Apparently some UNIX systems automatically reset the SIGCHLD # handler to SIG_DFL. Reset it just in case. self.set_sigchld_handler() def add_task(self, task): """Adds a Task to be processed with run().""" self.tasks.append(task) self.numnodes += 1 def update_tasks(self, writer): """Reaps tasks and starts as many new ones as allowed.""" # Mask signals to work around a Python bug: # http://bugs.python.org/issue1068268 # Since sigprocmask isn't in the stdlib, clear the SIGCHLD handler. # Since signals are masked, reap_tasks needs to be called once for # each loop. keep_running = True while keep_running: self.clear_sigchld_handler() self._start_tasks_once(writer) self.set_sigchld_handler() keep_running = self.reap_tasks() def _start_tasks_once(self, writer): """Starts tasks once. Due to http://bugs.python.org/issue1068268, signals must be masked when this method is called. """ while 0 < len(self.tasks) and len(self.running) < self.limit: task = self.tasks.pop(0) self.running.append(task) task.start(self.next_nodenum, self.numnodes, self.iomap, writer, self.askpass_socket) self.next_nodenum += 1 def reap_tasks(self): """Checks to see if any tasks have terminated. After cleaning up, returns the number of tasks that finished. """ still_running = [] finished_count = 0 for task in self.running: if task.running(): still_running.append(task) else: self.finished(task) finished_count += 1 self.running = still_running return finished_count def check_timeout(self): """Kills timed-out processes and returns the lowest time left.""" if self.timeout <= 0: return None min_timeleft = None for task in self.running: timeleft = self.timeout - task.elapsed() if timeleft <= 0: task.timedout() continue if min_timeleft is None or timeleft < min_timeleft: min_timeleft = timeleft if min_timeleft is None: return 0 else: return max(0, min_timeleft) def interrupted(self): """Cleans up after a keyboard interrupt.""" for task in self.running: task.interrupted() self.finished(task) for task in self.tasks: task.cancel() self.finished(task) def finished(self, task): """Marks a task as complete and reports its status to stdout.""" self.done.append(task) n = len(self.done) task.report(n) class IOMap(object): """A manager for file descriptors and their associated handlers. The poll method dispatches events to the appropriate handlers. """ def __init__(self): self.readmap = {} self.writemap = {} # Setup the wakeup file descriptor to avoid hanging on lost signals. wakeup_readfd, wakeup_writefd = os.pipe() fcntl.fcntl(wakeup_writefd, fcntl.F_SETFL, os.O_NONBLOCK) self.register_read(wakeup_readfd, self.wakeup_handler) signal.set_wakeup_fd(wakeup_writefd) def register_read(self, fd, handler): """Registers an IO handler for a file descriptor for reading.""" self.readmap[fd] = handler def register_write(self, fd, handler): """Registers an IO handler for a file descriptor for writing.""" self.writemap[fd] = handler def unregister(self, fd): """Unregisters the given file descriptor.""" if fd in self.readmap: del self.readmap[fd] if fd in self.writemap: del self.writemap[fd] def poll(self, timeout=None): """Performs a poll and dispatches the resulting events.""" if not self.readmap and not self.writemap: return rlist = list(self.readmap) wlist = list(self.writemap) try: rlist, wlist, _ = select.select(rlist, wlist, [], timeout) except select.error: _, e, _ = sys.exc_info() errno = e.args[0] if errno == EINTR: return else: raise for fd in rlist: handler = self.readmap[fd] handler(fd, self) for fd in wlist: handler = self.writemap[fd] handler(fd, self) def wakeup_handler(self, fd, iomap): """Handles read events on the signal wakeup pipe. This ensures that SIGCHLD signals aren't lost. """ try: os.read(fd, READ_SIZE) except (OSError, IOError): _, e, _ = sys.exc_info() errno, message = e.args if errno != EINTR: sys.stderr.write('Fatal error reading from wakeup pipe: %s\n' % message) raise FatalError class PollIOMap(IOMap): """A manager for file descriptors and their associated handlers. The poll method dispatches events to the appropriate handlers. Note that `select.poll` is not available on all operating systems. """ def __init__(self): self._poller = select.poll() super(PollIOMap, self).__init__() def register_read(self, fd, handler): """Registers an IO handler for a file descriptor for reading.""" super(PollIOMap, self).register_read(fd, handler) self._poller.register(fd, select.POLLIN) def register_write(self, fd, handler): """Registers an IO handler for a file descriptor for writing.""" super(PollIOMap, self).register_write(fd, handler) self._poller.register(fd, select.POLLOUT) def unregister(self, fd): """Unregisters the given file descriptor.""" super(PollIOMap, self).unregister(fd) self._poller.unregister(fd) def poll(self, timeout=None): """Performs a poll and dispatches the resulting events.""" if not self.readmap and not self.writemap: return try: event_list = self._poller.poll(timeout) except select.error: _, e, _ = sys.exc_info() errno = e.args[0] if errno == EINTR: return else: raise for fd, event in event_list: if event & (select.POLLIN | select.POLLHUP): handler = self.readmap[fd] handler(fd, self) if event & (select.POLLOUT | select.POLLERR): handler = self.writemap[fd] handler(fd, self) def make_iomap(): """Return a new IOMap or PollIOMap as appropriate. Since `select.poll` is not implemented on all platforms, this ensures that the most appropriate implementation is used. """ if hasattr(select, 'poll'): return PollIOMap() else: return IOMap() class Writer(threading.Thread): """Thread that writes to files by processing requests from a Queue. Until AIO becomes widely available, it is impossible to make a nonblocking write to an ordinary file. The Writer thread processes all writing to ordinary files so that the main thread can work without blocking. """ OPEN = object() EOF = object() ABORT = object() def __init__(self, outdir, errdir): threading.Thread.__init__(self) # A daemon thread automatically dies if the program is terminated. self.setDaemon(True) self.queue = queue.Queue() self.outdir = outdir self.errdir = errdir self.host_counts = {} self.files = {} def run(self): while True: filename, data = self.queue.get() if filename == self.ABORT: return if data == self.OPEN: self.files[filename] = None else: dest = self.files[filename] if data == self.EOF: if dest is not None: dest.close() else: if dest is None: dest = self.files[filename] = open( filename, 'wb', buffering=1) psshutil.set_cloexec(dest) dest.write(data) dest.flush() def open_files(self, host): """Called from another thread to create files for stdout and stderr. Returns a pair of filenames (outfile, errfile). These filenames are used as handles for future operations. Either or both may be None if outdir or errdir or not set. """ outfile = errfile = None if self.outdir or self.errdir: count = self.host_counts.get(host, 0) self.host_counts[host] = count + 1 if count: filename = "%s.%s" % (host, count) else: filename = host if self.outdir: outfile = os.path.join(self.outdir, filename) self.queue.put((outfile, self.OPEN)) if self.errdir: errfile = os.path.join(self.errdir, filename) self.queue.put((errfile, self.OPEN)) return outfile, errfile def write(self, filename, data): """Called from another thread to enqueue a write.""" self.queue.put((filename, data)) def close(self, filename): """Called from another thread to close the given file.""" self.queue.put((filename, self.EOF)) def signal_quit(self): """Called from another thread to request the Writer to quit.""" self.queue.put((self.ABORT, None)) pssh-2.3.4/psshlib/pardo.py000066400000000000000000000021301364227332400156220ustar00rootroot00000000000000# Copyright (c) 2018, Jeffrey Lund import itertools import os NODE_NUM = int(os.environ.get('PSSH_NODENUM', '0')) NUM_NODES = int(os.environ.get('PSSH_NUMNODES', '1')) def pardo(xs): """ Helper function for splitting up work using pssh. Assuming the environmental variables PSSH_NODENUM and PSSH_NUMNODES are set, will yield only the subset of xs which corespond to this node's work. If these variables are not set, then every value of xs will be yielded. """ task_no = -1 for i, x in enumerate(xs): task_no += 1 if task_no % NUM_NODES != NODE_NUM: continue yield x def prange(*args): """ A shortcut for pardo(range(*args)). """ yield from pardo(range(*args)) def penumerate(iterable, start=0): """ A shortchut for pardo(enumerate(iterable, start=start)). """ yield from pardo(enumerate(iterable, start=start)) def pproduct(*iterables, repeat=1): """ A shortcut for pardo(itertools.product(*iterables, repeat=repeat)). """ yield from pardo(itertools.product(*iterables, repeat=repeat)) pssh-2.3.4/psshlib/psshutil.py000066400000000000000000000062261364227332400164020ustar00rootroot00000000000000# Copyright (c) 2009-2012, Andrew McNabb # Copyright (c) 2003-2008, Brent N. Chun import fcntl import re import sys import fnmatch HOST_FORMAT = 'Host format is [user@]host[:port] [user]' def read_host_files(paths, host_glob, default_user=None, default_port=None): """Reads the given host files. Returns a list of (host, port, user) triples. """ hosts = [] if paths: for path in paths: hosts.extend(read_host_file(path, host_glob, default_user=default_user)) return hosts def read_host_file(path, host_glob, default_user=None, default_port=None): """Reads the given host file. Lines are of the form: host[:port] [login]. Returns a list of (host, port, user) triples. """ lines = [] f = open(path) for line in f: lines.append(line.strip()) f.close() hosts = [] for line in lines: # remove trailing comments line = re.sub('#.*', '', line) line = line.strip() # skip blank lines (or lines with only comments) if not line: continue host, port, user = parse_host_entry(line, default_user, default_port) if host and (not host_glob or fnmatch.fnmatch(host, host_glob)): hosts.append((host, port, user)) return hosts # TODO: deprecate the second host field and standardize on the # [user@]host[:port] format. def parse_host_entry(line, default_user, default_port): """Parses a single host entry. This may take either the of the form [user@]host[:port] or host[:port][ user]. Returns a (host, port, user) triple. """ fields = line.split() if len(fields) > 2: sys.stderr.write('Bad line: "%s". Format should be' ' [user@]host[:port] [user]\n' % line) return None, None, None host_field = fields[0] host, port, user = parse_host(host_field, default_port=default_port) if len(fields) == 2: if user is None: user = fields[1] else: sys.stderr.write('User specified twice in line: "%s"\n' % line) return None, None, None if user is None: user = default_user return host, port, user def parse_host_string(host_string, default_user=None, default_port=None): """Parses a whitespace-delimited string of "[user@]host[:port]" entries. Returns a list of (host, port, user) triples. """ hosts = [] entries = host_string.split() for entry in entries: hosts.append(parse_host(entry, default_user, default_port)) return hosts def parse_host(host, default_user=None, default_port=None): """Parses host entries of the form "[user@]host[:port]". Returns a (host, port, user) triple. """ user = default_user port = default_port if '@' in host: user, host = host.split('@', 1) if ':' in host: host, port = host.rsplit(':', 1) return (host, port, user) def set_cloexec(filelike): """Sets the underlying filedescriptor to automatically close on exec. If set_cloexec is called for all open files, then subprocess.Popen does not require the close_fds option. """ fcntl.fcntl(filelike.fileno(), fcntl.FD_CLOEXEC, 1) pssh-2.3.4/psshlib/task.py000066400000000000000000000241171364227332400154700ustar00rootroot00000000000000# Copyright (c) 2018, Jeffrey Lund # Copyright (c) 2009-2012, Andrew McNabb from errno import EINTR from subprocess import Popen, PIPE import os import signal import sys import time import traceback from psshlib import askpass_client from psshlib import color BUFFER_SIZE = 1 << 16 try: bytes except NameError: bytes = str class Task(object): """Starts a process and manages its input and output. Upon completion, the `exitstatus` attribute is set to the exit status of the process. """ def __init__(self, host, port, user, cmd, opts, stdin=None): self.exitstatus = None self.host = host self.pretty_host = host self.port = port self.cmd = cmd if user != opts.user: self.pretty_host = '@'.join((user, self.pretty_host)) if port: self.pretty_host = ':'.join((self.pretty_host, port)) self.proc = None self.writer = None self.timestamp = None self.failures = [] self.killed = False self.inputbuffer = stdin self.byteswritten = 0 self.outputbuffer = bytes() self.errorbuffer = bytes() self.stdin = None self.stdout = None self.stderr = None self.outfile = None self.errfile = None # Set options. self.verbose = opts.verbose try: self.print_out = bool(opts.print_out) except AttributeError: self.print_out = False try: self.inline = bool(opts.inline) except AttributeError: self.inline = False try: self.inline_stdout = bool(opts.inline_stdout) except AttributeError: self.inline_stdout = False def start(self, nodenum, numnodes, iomap, writer, askpass_socket=None): """Starts the process and registers files with the IOMap.""" self.writer = writer if writer: self.outfile, self.errfile = writer.open_files(self.pretty_host) # Set up the environment. environ = os.environ.copy() environ['PSSH_NODENUM'] = str(nodenum) environ['PSSH_NUMNODES'] = str(numnodes) environ['PSSH_HOST'] = self.host # Disable the GNOME pop-up password dialog and allow ssh to use # askpass.py to get a provided password. If the module file is # askpass.pyc, we replace the extension. environ['SSH_ASKPASS'] = askpass_client.executable_path() if askpass_socket: environ['PSSH_ASKPASS_SOCKET'] = askpass_socket if self.verbose: environ['PSSH_ASKPASS_VERBOSE'] = '1' # Work around a mis-feature in ssh where it won't call SSH_ASKPASS # if DISPLAY is unset. if 'DISPLAY' not in environ: environ['DISPLAY'] = 'pssh-gibberish' # Create the subprocess. Since we carefully call set_cloexec() on # all open files, we specify close_fds=False. self.proc = Popen(self.cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=False, preexec_fn=os.setsid, env=environ) self.timestamp = time.time() if self.inputbuffer: self.stdin = self.proc.stdin iomap.register_write(self.stdin.fileno(), self.handle_stdin) else: self.proc.stdin.close() self.stdout = self.proc.stdout iomap.register_read(self.stdout.fileno(), self.handle_stdout) self.stderr = self.proc.stderr iomap.register_read(self.stderr.fileno(), self.handle_stderr) def _kill(self): """Signals the process to terminate.""" if self.proc: try: os.kill(-self.proc.pid, signal.SIGKILL) except OSError: # If the kill fails, then just assume the process is dead. pass self.killed = True def timedout(self): """Kills the process and registers a timeout error.""" if not self.killed: self._kill() self.failures.append('Timed out') def interrupted(self): """Kills the process and registers an keyboard interrupt error.""" if not self.killed: self._kill() self.failures.append('Interrupted') def cancel(self): """Stops a task that has not started.""" self.failures.append('Cancelled') def elapsed(self): """Finds the time in seconds since the process was started.""" return time.time() - self.timestamp def running(self): """Finds if the process has terminated and saves the return code.""" # don't check self.stderr; it's still open when ControlPersist=yes is # set for ssh if self.stdin or self.stdout: return True if self.proc: self.exitstatus = self.proc.poll() if self.exitstatus is None: if self.killed: # Set the exitstatus to what it would be if we waited. self.exitstatus = -signal.SIGKILL return False else: return True else: if self.exitstatus < 0: message = 'Killed by signal %s' % (-self.exitstatus) self.failures.append(message) elif self.exitstatus > 0: message = 'Exited with error code %s' % self.exitstatus self.failures.append(message) self.proc = None return False def handle_stdin(self, fd, iomap): """Called when the process's standard input is ready for writing.""" try: start = self.byteswritten if start < len(self.inputbuffer): chunk = self.inputbuffer[start:start+BUFFER_SIZE] self.byteswritten = start + os.write(fd, chunk) else: self.close_stdin(iomap) except (OSError, IOError): _, e, _ = sys.exc_info() if e.errno != EINTR: self.close_stdin(iomap) self.log_exception(e) def close_stdin(self, iomap): if self.stdin: iomap.unregister(self.stdin.fileno()) self.stdin.close() self.stdin = None def handle_stdout(self, fd, iomap): """Called when the process's standard output is ready for reading.""" try: buf = os.read(fd, BUFFER_SIZE) if buf: if self.inline or self.inline_stdout: self.outputbuffer += buf if self.outfile: self.writer.write(self.outfile, buf) if self.print_out: text = buf.decode(errors='replace') sys.stdout.write('%s: %s' % (self.host, text)) if text[-1] != '\n': sys.stdout.write('\n') else: self.close_stdout(iomap) except (OSError, IOError): _, e, _ = sys.exc_info() if e.errno != EINTR: self.close_stdout(iomap) self.log_exception(e) def close_stdout(self, iomap): if self.stdout: iomap.unregister(self.stdout.fileno()) self.stdout.close() self.stdout = None if self.outfile: self.writer.close(self.outfile) self.outfile = None def handle_stderr(self, fd, iomap): """Called when the process's standard error is ready for reading.""" try: buf = os.read(fd, BUFFER_SIZE) if buf: if self.inline: self.errorbuffer += buf if self.errfile: self.writer.write(self.errfile, buf) else: self.close_stderr(iomap) except (OSError, IOError): _, e, _ = sys.exc_info() if e.errno != EINTR: self.close_stderr(iomap) self.log_exception(e) def close_stderr(self, iomap): if self.stderr: iomap.unregister(self.stderr.fileno()) self.stderr.close() self.stderr = None if self.errfile: self.writer.close(self.errfile) self.errfile = None def log_exception(self, e): """Saves a record of the most recent exception for error reporting.""" if self.verbose: exc_type, exc_value, exc_traceback = sys.exc_info() exc = ("Exception: %s, %s, %s" % (exc_type, exc_value, traceback.format_tb(exc_traceback))) else: exc = str(e) self.failures.append(exc) def report(self, n): """Pretty prints a status report after the Task completes.""" error = ', '.join(self.failures) tstamp = time.asctime().split()[3] # Current time if color.has_colors(sys.stdout): progress = color.c("[%s]" % color.B(n)) success = color.g("[%s]" % color.B("SUCCESS")) failure = color.r("[%s]" % color.B("FAILURE")) stderr = color.r("Stderr: ") error = color.r(color.B(error)) else: progress = "[%s]" % n success = "[SUCCESS]" failure = "[FAILURE]" stderr = "Stderr: " host = self.pretty_host if self.failures: print(' '.join((progress, tstamp, failure, host, error))) else: print(' '.join((progress, tstamp, success, host))) # NOTE: The extra flushes are to ensure that the data is output in # the correct order with the C implementation of io. if self.outputbuffer: sys.stdout.flush() try: sys.stdout.buffer.write(self.outputbuffer) sys.stdout.flush() except AttributeError: sys.stdout.write(self.outputbuffer) if self.errorbuffer: sys.stdout.write(stderr) # Flush the TextIOWrapper before writing to the binary buffer. sys.stdout.flush() try: sys.stdout.buffer.write(self.errorbuffer) except AttributeError: sys.stdout.write(self.errorbuffer) pssh-2.3.4/psshlib/version.py000066400000000000000000000000221364227332400162000ustar00rootroot00000000000000VERSION = '2.3.4' pssh-2.3.4/setup.py000077500000000000000000000032121364227332400142160ustar00rootroot00000000000000#!/usr/bin/env python import os from setuptools import setup from psshlib import version long_description = """PSSH (Parallel SSH) provides parallel versions of OpenSSH and related tools, including pssh, pscp, prsync, pnuke, and pslurp. The project includes psshlib which can be used within custom applications.""" setup( name = "pssh", version = version.VERSION, author = "Andrew McNabb", author_email = "amcnabb@mcnabbs.org", url = "https://github.com/lilydjwg/pssh", description = "Parallel version of OpenSSH and related tools", long_description = long_description, license = "BSD", platforms = ['linux'], classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: System Administrators", "License :: OSI Approved :: BSD License", "Operating System :: POSIX", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Clustering", "Topic :: System :: Networking", "Topic :: System :: Systems Administration", ], packages = ['psshlib'], scripts = [os.path.join("bin", p) for p in ["pssh", "pnuke", "prsync", "pslurp", "pscp", "pssh-askpass"]], data_files = [('share/man/man1', [ 'man/man1/pssh.1', 'man/man1/pscp.1', 'man/man1/prsync.1', 'man/man1/pslurp.1', 'man/man1/pnuke.1', ])], ) pssh-2.3.4/test/000077500000000000000000000000001364227332400134625ustar00rootroot00000000000000pssh-2.3.4/test/test.py000066400000000000000000000313431364227332400150170ustar00rootroot00000000000000#!/usr/bin/python # Copyright (c) 2009, Andrew McNabb # Copyright (c) 2003-2008, Brent N. Chun import os import subprocess import sys import shutil import tempfile import time import unittest basedir, bin = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0]))) sys.path.append("%s" % basedir) if os.getenv("TEST_HOSTS") is None: raise Exception("Must define TEST_HOSTS") g_hosts = os.getenv("TEST_HOSTS").split() if os.getenv("TEST_USER") is None: raise Exception("Must define TEST_USER") g_user = os.getenv("TEST_USER") class PsshTest(unittest.TestCase): def setUp(self): self.outDir = tempfile.mkdtemp() self.errDir = tempfile.mkdtemp() def tearDown(self): shutil.rmtree(self.errDir) shutil.rmtree(self.outDir) def testShortOpts(self): hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pssh -h %s -l %s -p 64 -o %s -e %s -t 60 -v -P -i uptime < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: stdout = open("%s/%s" % (self.outDir, host)).read() self.assert_(stdout.find("load average") != -1) def testLongOpts(self): hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pssh --hosts=%s --user=%s --par=64 --outdir=%s --errdir=%s --timeout=60 --verbose --print --inline uptime < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: stdout = open("%s/%s" % (self.outDir, host)).read() self.assert_(stdout.find("load average") != -1) def testStderr(self): hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pssh -h %s -l %s -p 64 -o %s -e %s -t 60 -v -P -i ls /doesnotexist < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: stdout = open("%s/%s" % (self.outDir, host)).read() self.assertEqual(stdout, "") stderr = open("%s/%s" % (self.errDir, host)).read() self.assert_(stderr.find("No such file or directory") != -1) class PscpTest(unittest.TestCase): def setUp(self): self.outDir = tempfile.mkdtemp() self.errDir = tempfile.mkdtemp() def tearDown(self): shutil.rmtree(self.errDir) shutil.rmtree(self.outDir) try: os.remove("/tmp/pssh.test") except OSError: pass def testShortOpts(self): for host in g_hosts: cmd = "ssh %s@%s rm -rf /tmp/pssh.test" % (g_user, host) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pscp -h %s -l %s -p 64 -o %s -e %s -t 60 /etc/hosts /tmp/pssh.test < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: cmd = "ssh %s@%s cat /tmp/pssh.test" % (g_user, host) data = os.popen(cmd).read() self.assertEqual(data, open("/etc/hosts").read()) def testLongOpts(self): for host in g_hosts: cmd = "ssh %s@%s rm -rf /tmp/pssh.test" % (g_user, host) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pscp --hosts=%s --user=%s --par=64 --outdir=%s --errdir=%s --timeout=60 /etc/hosts /tmp/pssh.test < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: cmd = "ssh %s@%s cat /tmp/pssh.test" % (g_user, host) data = os.popen(cmd).read() self.assertEqual(data, open("/etc/hosts").read()) def testRecursive(self): for host in g_hosts: cmd = "ssh %s@%s rm -rf /tmp/pssh.test" % (g_user, host) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pscp -r -h %s -l %s -p 64 -o %s -e %s -t 60 /etc/init.d /tmp/pssh.test < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) files = os.popen("ls -R /etc/init.d | sed 1d | sort").read().strip() for host in g_hosts: cmd = "ssh %s@%s ls -R /tmp/pssh.test | sed 1d | sort" % (g_user, host) data = os.popen(cmd).read().strip() self.assertEqual(data, files) class PslurpTest(unittest.TestCase): def setUp(self): self.outDir = tempfile.mkdtemp() self.errDir = tempfile.mkdtemp() def tearDown(self): shutil.rmtree(self.errDir) shutil.rmtree(self.outDir) def testShortOpts(self): if os.path.exists("/tmp/pssh.test"): try: os.remove("/tmp/pssh.test") except OSError: shutil.rmtree("/tmp/pssh.test") hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pslurp -L /tmp/pssh.test -h %s -l %s -p 64 -o %s -e %s -t 60 /etc/hosts hosts < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: cmd = "ssh %s@%s cat /etc/hosts" % (g_user, host) data = os.popen(cmd).read() self.assertEqual(data, open("/tmp/pssh.test/%s/hosts" % host).read()) def testLongOpts(self): if os.path.exists("/tmp/pssh.test"): try: os.remove("/tmp/pssh.test") except OSError: shutil.rmtree("/tmp/pssh.test") hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pslurp --localdir=/tmp/pssh.test --hosts=%s --user=%s --par=64 --outdir=%s --errdir=%s --timeout=60 /etc/hosts hosts < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: cmd = "ssh %s@%s cat /etc/hosts" % (g_user, host) data = os.popen(cmd).read() self.assertEqual(data, open("/tmp/pssh.test/%s/hosts" % host).read()) def testRecursive(self): if os.path.exists("/tmp/pssh.test"): try: os.remove("/tmp/pssh.test") except OSError: shutil.rmtree("/tmp/pssh.test") hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pslurp -r -L /tmp/pssh.test -h %s -l %s -p 64 -o %s -e %s -t 60 /etc/init.d init.d < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: cmd = "ssh %s@%s ls -R /etc/init.d | sed 1d | sort" % (g_user, host) data = os.popen(cmd).read() self.assertEqual(data, os.popen("ls -R /tmp/pssh.test/%s/init.d | sed 1d | sort" % host).read()) class PrsyncTest(unittest.TestCase): def setUp(self): self.outDir = tempfile.mkdtemp() self.errDir = tempfile.mkdtemp() def tearDown(self): shutil.rmtree(self.errDir) shutil.rmtree(self.outDir) def testShortOpts(self): for host in g_hosts: cmd = "ssh %s@%s rm -rf /tmp/pssh.test" % (g_user, host) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/prsync -h %s -l %s -p 64 -o %s -e %s -t 60 -a -z /etc/hosts /tmp/pssh.test < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: cmd = "ssh %s@%s cat /tmp/pssh.test" % (g_user, host) data = os.popen(cmd).read() self.assertEqual(data, open("/etc/hosts").read()) def testLongOpts(self): for host in g_hosts: cmd = "ssh %s@%s rm -rf /tmp/pssh.test" % (g_user, host) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/prsync --hosts=%s --user=%s --par=64 --outdir=%s --errdir=%s --timeout=60 --archive --compress /etc/hosts /tmp/pssh.test < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) for host in g_hosts: cmd = "ssh %s@%s cat /tmp/pssh.test" % (g_user, host) data = os.popen(cmd).read() self.assertEqual(data, open("/etc/hosts").read()) def testRecursive(self): for host in g_hosts: cmd = "ssh %s@%s rm -rf /tmp/pssh.test" % (g_user, host) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/prsync -r -h %s -l %s -p 64 -o %s -e %s -t 60 -a -z /etc/init.d/ /tmp/pssh.test < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) files = os.popen("ls -R /etc/init.d | sed 1d | sort").read().strip() for host in g_hosts: cmd = "ssh %s@%s ls -R /tmp/pssh.test | sed 1d | sort" % (g_user, host) data = os.popen(cmd).read().strip() self.assertEqual(data, files) class PnukeTest(unittest.TestCase): def setUp(self): self.outDir = tempfile.mkdtemp() self.errDir = tempfile.mkdtemp() def tearDown(self): shutil.rmtree(self.errDir) shutil.rmtree(self.outDir) def testShortOpts(self): hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pssh -h %s -l %s -p 64 -o %s -e %s -t 60 -v sleep 60 < /dev/null &" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) subprocess.call(cmd, shell=True) time.sleep(5) cmd = "%s/bin/pnuke -h %s -l %s -p 64 -o %s -e %s -t 60 -v sleep < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) print cmd rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) def testLongOpts(self): hostsFile = tempfile.NamedTemporaryFile() hostsFile.write("".join(map(lambda x: "%s\n" % x, g_hosts))) hostsFile.flush() cmd = "%s/bin/pssh --hosts=%s --user=%s --par=64 --outdir=%s --errdir=%s --timeout=60 --verbose sleep 60 < /dev/null &" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) subprocess.call(cmd, shell=True) time.sleep(5) cmd = "%s/bin/pnuke --hosts=%s --user=%s --par=64 --outdir=%s --errdir=%s --timeout=60 --verbose sleep < /dev/null" % (basedir, hostsFile.name, g_user, self.outDir, self.errDir) print cmd rv = subprocess.call(cmd, shell=True) self.assertEqual(rv, 0) if __name__ == '__main__': suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(PsshTest, "test")) suite.addTest(unittest.makeSuite(PscpTest, "test")) suite.addTest(unittest.makeSuite(PslurpTest, "test")) suite.addTest(unittest.makeSuite(PrsyncTest, "test")) suite.addTest(unittest.makeSuite(PnukeTest, "test")) unittest.TextTestRunner().run(suite)