pec2 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pec2/cli.rb +1 -9
- data/lib/pec2/pssh.rb +58 -28
- data/lib/pec2/version.rb +1 -1
- data/pec2.gemspec +4 -1
- data/spec/cli_spec.rb +0 -1
- data/spec/pssh_spec.rb +1 -54
- metadata +46 -24
- data/exe/bin/pnuke +0 -96
- data/exe/bin/prsync +0 -126
- data/exe/bin/pscp +0 -108
- data/exe/bin/pslurp +0 -129
- data/exe/bin/pssh +0 -118
- data/exe/bin/pssh-askpass +0 -11
- data/exe/man/man1/pnuke.1 +0 -268
- data/exe/man/man1/prsync.1 +0 -299
- data/exe/man/man1/pscp.1 +0 -271
- data/exe/man/man1/pslurp.1 +0 -280
- data/exe/man/man1/pssh.1 +0 -368
- data/exe/psshlib/__init__.py +0 -0
- data/exe/psshlib/askpass_client.py +0 -102
- data/exe/psshlib/askpass_server.py +0 -101
- data/exe/psshlib/cli.py +0 -110
- data/exe/psshlib/color.py +0 -39
- data/exe/psshlib/manager.py +0 -345
- data/exe/psshlib/psshutil.py +0 -108
- data/exe/psshlib/task.py +0 -288
- data/exe/psshlib/version.py +0 -1
data/exe/bin/prsync
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python
|
2
|
-
# -*- Mode: python -*-
|
3
|
-
|
4
|
-
# Copyright (c) 2009-2012, Andrew McNabb
|
5
|
-
# Copyright (c) 2003-2008, Brent N. Chun
|
6
|
-
|
7
|
-
"""Parallel rsync to the set of nodes in hosts.txt.
|
8
|
-
|
9
|
-
For each node, we essentially do a rsync -rv -e ssh local user@host:remote.
|
10
|
-
Note that remote must be an absolute path.
|
11
|
-
"""
|
12
|
-
|
13
|
-
import os
|
14
|
-
import re
|
15
|
-
import sys
|
16
|
-
|
17
|
-
parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0])))
|
18
|
-
if os.path.exists(os.path.join(parent, 'psshlib')):
|
19
|
-
sys.path.insert(0, parent)
|
20
|
-
|
21
|
-
from psshlib import psshutil
|
22
|
-
from psshlib.task import Task
|
23
|
-
from psshlib.manager import Manager, FatalError
|
24
|
-
from psshlib.cli import common_parser, common_defaults
|
25
|
-
|
26
|
-
def option_parser():
|
27
|
-
parser = common_parser()
|
28
|
-
parser.usage = "%prog [OPTIONS] local remote"
|
29
|
-
parser.epilog = ("Example: prsync -r -h hosts.txt -l irb2 foo " +
|
30
|
-
"/home/irb2/foo")
|
31
|
-
|
32
|
-
parser.add_option('-r', '--recursive', dest='recursive',
|
33
|
-
action='store_true', help='recusively copy directories (OPTIONAL)')
|
34
|
-
parser.add_option('-a', '--archive', dest='archive', action='store_true',
|
35
|
-
help='use rsync -a (archive mode) (OPTIONAL)')
|
36
|
-
parser.add_option('-z', '--compress', dest='compress', action='store_true',
|
37
|
-
help='use rsync compression (OPTIONAL)')
|
38
|
-
parser.add_option('-S', '--ssh-args', metavar="ARGS", dest='ssh_args',
|
39
|
-
action='store', help='extra arguments for ssh')
|
40
|
-
|
41
|
-
return parser
|
42
|
-
|
43
|
-
def parse_args():
|
44
|
-
parser = option_parser()
|
45
|
-
defaults = common_defaults()
|
46
|
-
parser.set_defaults(**defaults)
|
47
|
-
opts, args = parser.parse_args()
|
48
|
-
|
49
|
-
if len(args) < 1:
|
50
|
-
parser.error('Paths not specified.')
|
51
|
-
|
52
|
-
if len(args) < 2:
|
53
|
-
parser.error('Remote path not specified.')
|
54
|
-
|
55
|
-
if len(args) > 2:
|
56
|
-
parser.error('Extra arguments given after the remote path.')
|
57
|
-
|
58
|
-
if not opts.host_files and not opts.host_strings:
|
59
|
-
parser.error('Hosts not specified.')
|
60
|
-
|
61
|
-
return opts, args
|
62
|
-
|
63
|
-
def do_prsync(hosts, local, remote, opts):
|
64
|
-
if opts.outdir and not os.path.exists(opts.outdir):
|
65
|
-
os.makedirs(opts.outdir)
|
66
|
-
if opts.errdir and not os.path.exists(opts.errdir):
|
67
|
-
os.makedirs(opts.errdir)
|
68
|
-
manager = Manager(opts)
|
69
|
-
for host, port, user in hosts:
|
70
|
-
ssh = ['ssh']
|
71
|
-
if opts.options:
|
72
|
-
for opt in opts.options:
|
73
|
-
ssh += ['-o', opt]
|
74
|
-
if port:
|
75
|
-
ssh += ['-p', port]
|
76
|
-
if opts.ssh_args:
|
77
|
-
ssh += [opts.ssh_args]
|
78
|
-
|
79
|
-
cmd = ['rsync', '-e', ' '.join(ssh)]
|
80
|
-
if opts.verbose:
|
81
|
-
cmd.append('-v')
|
82
|
-
if opts.recursive:
|
83
|
-
cmd.append('-r')
|
84
|
-
if opts.archive:
|
85
|
-
cmd.append('-a')
|
86
|
-
if opts.compress:
|
87
|
-
cmd.append('-z')
|
88
|
-
if opts.extra:
|
89
|
-
cmd.extend(opts.extra)
|
90
|
-
cmd.append(local)
|
91
|
-
if user:
|
92
|
-
cmd.append('%s@%s:%s' % (user, host, remote))
|
93
|
-
else:
|
94
|
-
cmd.append('%s:%s' % (host, remote))
|
95
|
-
t = Task(host, port, user, cmd, opts)
|
96
|
-
manager.add_task(t)
|
97
|
-
try:
|
98
|
-
statuses = manager.run()
|
99
|
-
except FatalError:
|
100
|
-
sys.exit(1)
|
101
|
-
|
102
|
-
if min(statuses) < 0:
|
103
|
-
# At least one process was killed.
|
104
|
-
sys.exit(3)
|
105
|
-
for status in statuses:
|
106
|
-
if status != 0:
|
107
|
-
sys.exit(4)
|
108
|
-
|
109
|
-
if __name__ == "__main__":
|
110
|
-
opts, args = parse_args()
|
111
|
-
local = args[0]
|
112
|
-
remote = args[1]
|
113
|
-
if not re.match("^/", remote):
|
114
|
-
print("Remote path %s must be an absolute path" % remote)
|
115
|
-
sys.exit(3)
|
116
|
-
try:
|
117
|
-
hosts = psshutil.read_host_files(opts.host_files,
|
118
|
-
default_user=opts.user)
|
119
|
-
except IOError:
|
120
|
-
_, e, _ = sys.exc_info()
|
121
|
-
sys.stderr.write('Could not open hosts file: %s\n' % e.strerror)
|
122
|
-
sys.exit(1)
|
123
|
-
if opts.host_strings:
|
124
|
-
for s in opts.host_strings:
|
125
|
-
hosts.extend(psshutil.parse_host_string(s, default_user=opts.user))
|
126
|
-
do_prsync(hosts, local, remote, opts)
|
data/exe/bin/pscp
DELETED
@@ -1,108 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python
|
2
|
-
# -*- Mode: python -*-
|
3
|
-
|
4
|
-
# Copyright (c) 2009-2012, Andrew McNabb
|
5
|
-
# Copyright (c) 2003-2008, Brent N. Chun
|
6
|
-
|
7
|
-
"""Parallel scp to the set of nodes in hosts.txt.
|
8
|
-
|
9
|
-
For each node, we essentially do a scp [-r] local user@host:remote. This
|
10
|
-
program also uses the -q (quiet) and -C (compression) options. Note that
|
11
|
-
remote must be an absolute path.
|
12
|
-
"""
|
13
|
-
|
14
|
-
import os
|
15
|
-
import re
|
16
|
-
import sys
|
17
|
-
|
18
|
-
parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0])))
|
19
|
-
if os.path.exists(os.path.join(parent, 'psshlib')):
|
20
|
-
sys.path.insert(0, parent)
|
21
|
-
|
22
|
-
from psshlib import psshutil
|
23
|
-
from psshlib.task import Task
|
24
|
-
from psshlib.manager import Manager, FatalError
|
25
|
-
from psshlib.cli import common_parser, common_defaults
|
26
|
-
|
27
|
-
def option_parser():
|
28
|
-
parser = common_parser()
|
29
|
-
parser.usage = "%prog [OPTIONS] local remote"
|
30
|
-
parser.epilog = ("Example: pscp -h hosts.txt -l irb2 foo.txt " +
|
31
|
-
"/home/irb2/foo.txt")
|
32
|
-
|
33
|
-
parser.add_option('-r', '--recursive', dest='recursive',
|
34
|
-
action='store_true', help='recusively copy directories (OPTIONAL)')
|
35
|
-
|
36
|
-
return parser
|
37
|
-
|
38
|
-
def parse_args():
|
39
|
-
parser = option_parser()
|
40
|
-
defaults = common_defaults()
|
41
|
-
parser.set_defaults(**defaults)
|
42
|
-
opts, args = parser.parse_args()
|
43
|
-
|
44
|
-
if len(args) < 1:
|
45
|
-
parser.error('Paths not specified.')
|
46
|
-
|
47
|
-
if len(args) < 2:
|
48
|
-
parser.error('Remote path not specified.')
|
49
|
-
|
50
|
-
if not opts.host_files and not opts.host_strings:
|
51
|
-
parser.error('Hosts not specified.')
|
52
|
-
|
53
|
-
return opts, args
|
54
|
-
|
55
|
-
def do_pscp(hosts, localargs, remote, opts):
|
56
|
-
if opts.outdir and not os.path.exists(opts.outdir):
|
57
|
-
os.makedirs(opts.outdir)
|
58
|
-
if opts.errdir and not os.path.exists(opts.errdir):
|
59
|
-
os.makedirs(opts.errdir)
|
60
|
-
manager = Manager(opts)
|
61
|
-
for host, port, user in hosts:
|
62
|
-
cmd = ['scp', '-qC']
|
63
|
-
if opts.options:
|
64
|
-
for opt in opts.options:
|
65
|
-
cmd += ['-o', opt]
|
66
|
-
if port:
|
67
|
-
cmd += ['-P', port]
|
68
|
-
if opts.recursive:
|
69
|
-
cmd.append('-r')
|
70
|
-
if opts.extra:
|
71
|
-
cmd.extend(opts.extra)
|
72
|
-
cmd.extend(localargs)
|
73
|
-
if user:
|
74
|
-
cmd.append('%s@%s:%s' % (user, host, remote))
|
75
|
-
else:
|
76
|
-
cmd.append('%s:%s' % (host, remote))
|
77
|
-
t = Task(host, port, user, cmd, opts)
|
78
|
-
manager.add_task(t)
|
79
|
-
try:
|
80
|
-
statuses = manager.run()
|
81
|
-
except FatalError:
|
82
|
-
sys.exit(1)
|
83
|
-
|
84
|
-
if min(statuses) < 0:
|
85
|
-
# At least one process was killed.
|
86
|
-
sys.exit(3)
|
87
|
-
for status in statuses:
|
88
|
-
if status != 0:
|
89
|
-
sys.exit(4)
|
90
|
-
|
91
|
-
if __name__ == "__main__":
|
92
|
-
opts, args = parse_args()
|
93
|
-
localargs = args[0:-1]
|
94
|
-
remote = args[-1]
|
95
|
-
if not re.match("^/", remote):
|
96
|
-
print("Remote path %s must be an absolute path" % remote)
|
97
|
-
sys.exit(3)
|
98
|
-
try:
|
99
|
-
hosts = psshutil.read_host_files(opts.host_files,
|
100
|
-
default_user=opts.user)
|
101
|
-
except IOError:
|
102
|
-
_, e, _ = sys.exc_info()
|
103
|
-
sys.stderr.write('Could not open hosts file: %s\n' % e.strerror)
|
104
|
-
sys.exit(1)
|
105
|
-
if opts.host_strings:
|
106
|
-
for s in opts.host_strings:
|
107
|
-
hosts.extend(psshutil.parse_host_string(s, default_user=opts.user))
|
108
|
-
do_pscp(hosts, localargs, remote, opts)
|
data/exe/bin/pslurp
DELETED
@@ -1,129 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python
|
2
|
-
# -*- Mode: python -*-
|
3
|
-
|
4
|
-
# Copyright (c) 2009-2012, Andrew McNabb
|
5
|
-
# Copyright (c) 2003-2008, Brent N. Chun
|
6
|
-
|
7
|
-
"""Parallel scp from the set of nodes in hosts.txt.
|
8
|
-
|
9
|
-
For each node, we essentially do a scp [-r] user@host:remote
|
10
|
-
outdir/<node>/local. This program also uses the -q (quiet) and -C
|
11
|
-
(compression) options. Note that remote must be an absolute path.
|
12
|
-
"""
|
13
|
-
|
14
|
-
import os
|
15
|
-
import re
|
16
|
-
import sys
|
17
|
-
|
18
|
-
parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0])))
|
19
|
-
if os.path.exists(os.path.join(parent, 'psshlib')):
|
20
|
-
sys.path.insert(0, parent)
|
21
|
-
|
22
|
-
from psshlib import psshutil
|
23
|
-
from psshlib.task import Task
|
24
|
-
from psshlib.manager import Manager, FatalError
|
25
|
-
from psshlib.cli import common_parser, common_defaults
|
26
|
-
|
27
|
-
def option_parser():
|
28
|
-
parser = common_parser()
|
29
|
-
parser.usage = "%prog [OPTIONS] remote local"
|
30
|
-
parser.epilog = ("Example: pslurp -h hosts.txt -L /tmp/outdir -l irb2 " +
|
31
|
-
" /home/irb2/foo.txt foo.txt")
|
32
|
-
|
33
|
-
parser.add_option('-r', '--recursive', dest='recursive',
|
34
|
-
action='store_true', help='recusively copy directories (OPTIONAL)')
|
35
|
-
parser.add_option('-L', '--localdir', dest='localdir',
|
36
|
-
help='output directory for remote file copies')
|
37
|
-
|
38
|
-
return parser
|
39
|
-
|
40
|
-
def parse_args():
|
41
|
-
parser = option_parser()
|
42
|
-
defaults = common_defaults()
|
43
|
-
parser.set_defaults(**defaults)
|
44
|
-
opts, args = parser.parse_args()
|
45
|
-
|
46
|
-
if len(args) < 1:
|
47
|
-
parser.error('Paths not specified.')
|
48
|
-
|
49
|
-
if len(args) < 2:
|
50
|
-
parser.error('Local path not specified.')
|
51
|
-
|
52
|
-
if len(args) > 2:
|
53
|
-
parser.error('Extra arguments given after the local path.')
|
54
|
-
|
55
|
-
if not opts.host_files and not opts.host_strings:
|
56
|
-
parser.error('Hosts not specified.')
|
57
|
-
|
58
|
-
return opts, args
|
59
|
-
|
60
|
-
def do_pslurp(hosts, remote, local, opts):
|
61
|
-
if opts.localdir and not os.path.exists(opts.localdir):
|
62
|
-
os.makedirs(opts.localdir)
|
63
|
-
if opts.outdir and not os.path.exists(opts.outdir):
|
64
|
-
os.makedirs(opts.outdir)
|
65
|
-
if opts.errdir and not os.path.exists(opts.errdir):
|
66
|
-
os.makedirs(opts.errdir)
|
67
|
-
for host, port, user in hosts:
|
68
|
-
if opts.localdir:
|
69
|
-
dirname = "%s/%s" % (opts.localdir, host)
|
70
|
-
else:
|
71
|
-
dirname = host
|
72
|
-
if not os.path.exists(dirname):
|
73
|
-
os.mkdir(dirname)
|
74
|
-
manager = Manager(opts)
|
75
|
-
for host, port, user in hosts:
|
76
|
-
if opts.localdir:
|
77
|
-
localpath = "%s/%s/%s" % (opts.localdir, host, local)
|
78
|
-
else:
|
79
|
-
localpath = "%s/%s" % (host, local)
|
80
|
-
cmd = ['scp', '-qC']
|
81
|
-
if opts.options:
|
82
|
-
for opt in opts.options:
|
83
|
-
cmd += ['-o', opt]
|
84
|
-
if port:
|
85
|
-
cmd += ['-P', port]
|
86
|
-
if opts.recursive:
|
87
|
-
cmd.append('-r')
|
88
|
-
if opts.extra:
|
89
|
-
cmd.extend(opts.extra)
|
90
|
-
if user:
|
91
|
-
cmd.append('%s@%s:%s' % (user, host, remote))
|
92
|
-
else:
|
93
|
-
cmd.append('%s:%s' % (host, remote))
|
94
|
-
cmd.append(localpath)
|
95
|
-
t = Task(host, port, user, cmd, opts)
|
96
|
-
manager.add_task(t)
|
97
|
-
try:
|
98
|
-
statuses = manager.run()
|
99
|
-
except FatalError:
|
100
|
-
sys.exit(1)
|
101
|
-
|
102
|
-
if min(statuses) < 0:
|
103
|
-
# At least one process was killed.
|
104
|
-
sys.exit(3)
|
105
|
-
for status in statuses:
|
106
|
-
if status == 255:
|
107
|
-
sys.exit(4)
|
108
|
-
for status in statuses:
|
109
|
-
if status != 0:
|
110
|
-
sys.exit(5)
|
111
|
-
|
112
|
-
if __name__ == "__main__":
|
113
|
-
opts, args = parse_args()
|
114
|
-
remote = args[0]
|
115
|
-
local = args[1]
|
116
|
-
if not re.match("^/", remote):
|
117
|
-
print("Remote path %s must be an absolute path" % remote)
|
118
|
-
sys.exit(3)
|
119
|
-
try:
|
120
|
-
hosts = psshutil.read_host_files(opts.host_files,
|
121
|
-
default_user=opts.user)
|
122
|
-
except IOError:
|
123
|
-
_, e, _ = sys.exc_info()
|
124
|
-
sys.stderr.write('Could not open hosts file: %s\n' % e.strerror)
|
125
|
-
sys.exit(1)
|
126
|
-
if opts.host_strings:
|
127
|
-
for s in opts.host_strings:
|
128
|
-
hosts.extend(psshutil.parse_host_string(s, default_user=opts.user))
|
129
|
-
do_pslurp(hosts, remote, local, opts)
|
data/exe/bin/pssh
DELETED
@@ -1,118 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python
|
2
|
-
# -*- Mode: python -*-
|
3
|
-
|
4
|
-
# Copyright (c) 2009-2012, Andrew McNabb
|
5
|
-
# Copyright (c) 2003-2008, Brent N. Chun
|
6
|
-
|
7
|
-
"""Parallel ssh to the set of nodes in hosts.txt.
|
8
|
-
|
9
|
-
For each node, this essentially does an "ssh host -l user prog [arg0] [arg1]
|
10
|
-
...". The -o option can be used to store stdout from each remote node in a
|
11
|
-
directory. Each output file in that directory will be named by the
|
12
|
-
corresponding remote node's hostname or IP address.
|
13
|
-
"""
|
14
|
-
|
15
|
-
import fcntl
|
16
|
-
import os
|
17
|
-
import sys
|
18
|
-
|
19
|
-
parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0])))
|
20
|
-
if os.path.exists(os.path.join(parent, 'psshlib')):
|
21
|
-
sys.path.insert(0, parent)
|
22
|
-
|
23
|
-
from psshlib import psshutil
|
24
|
-
from psshlib.manager import Manager, FatalError
|
25
|
-
from psshlib.task import Task
|
26
|
-
from psshlib.cli import common_parser, common_defaults
|
27
|
-
|
28
|
-
_DEFAULT_TIMEOUT = 60
|
29
|
-
|
30
|
-
def option_parser():
|
31
|
-
parser = common_parser()
|
32
|
-
parser.usage = "%prog [OPTIONS] command [...]"
|
33
|
-
parser.epilog = "Example: pssh -h hosts.txt -l irb2 -o /tmp/foo uptime"
|
34
|
-
|
35
|
-
parser.add_option('-i', '--inline', dest='inline', action='store_true',
|
36
|
-
help='inline aggregated output and error for each server')
|
37
|
-
parser.add_option('--inline-stdout', dest='inline_stdout',
|
38
|
-
action='store_true',
|
39
|
-
help='inline standard output for each server')
|
40
|
-
parser.add_option('-I', '--send-input', dest='send_input',
|
41
|
-
action='store_true',
|
42
|
-
help='read from standard input and send as input to ssh')
|
43
|
-
parser.add_option('-P', '--print', dest='print_out', action='store_true',
|
44
|
-
help='print output as we get it')
|
45
|
-
|
46
|
-
return parser
|
47
|
-
|
48
|
-
def parse_args():
|
49
|
-
parser = option_parser()
|
50
|
-
defaults = common_defaults(timeout=_DEFAULT_TIMEOUT)
|
51
|
-
parser.set_defaults(**defaults)
|
52
|
-
opts, args = parser.parse_args()
|
53
|
-
|
54
|
-
if len(args) == 0 and not opts.send_input:
|
55
|
-
parser.error('Command not specified.')
|
56
|
-
|
57
|
-
if not opts.host_files and not opts.host_strings:
|
58
|
-
parser.error('Hosts not specified.')
|
59
|
-
|
60
|
-
return opts, args
|
61
|
-
|
62
|
-
def do_pssh(hosts, cmdline, opts):
|
63
|
-
if opts.outdir and not os.path.exists(opts.outdir):
|
64
|
-
os.makedirs(opts.outdir)
|
65
|
-
if opts.errdir and not os.path.exists(opts.errdir):
|
66
|
-
os.makedirs(opts.errdir)
|
67
|
-
if opts.send_input:
|
68
|
-
stdin = sys.stdin.read()
|
69
|
-
else:
|
70
|
-
stdin = None
|
71
|
-
manager = Manager(opts)
|
72
|
-
for host, port, user in hosts:
|
73
|
-
cmd = ['ssh', host, '-o', 'NumberOfPasswordPrompts=1',
|
74
|
-
'-o', 'SendEnv=PSSH_NODENUM PSSH_HOST']
|
75
|
-
if opts.options:
|
76
|
-
for opt in opts.options:
|
77
|
-
cmd += ['-o', opt]
|
78
|
-
if user:
|
79
|
-
cmd += ['-l', user]
|
80
|
-
if port:
|
81
|
-
cmd += ['-p', port]
|
82
|
-
if opts.extra:
|
83
|
-
cmd.extend(opts.extra)
|
84
|
-
if cmdline:
|
85
|
-
cmd.append(cmdline)
|
86
|
-
t = Task(host, port, user, cmd, opts, stdin)
|
87
|
-
manager.add_task(t)
|
88
|
-
try:
|
89
|
-
statuses = manager.run()
|
90
|
-
except FatalError:
|
91
|
-
sys.exit(1)
|
92
|
-
|
93
|
-
if min(statuses) < 0:
|
94
|
-
# At least one process was killed.
|
95
|
-
sys.exit(3)
|
96
|
-
# The any builtin was introduced in Python 2.5 (so we can't use it yet):
|
97
|
-
#elif any(x==255 for x in statuses):
|
98
|
-
for status in statuses:
|
99
|
-
if status == 255:
|
100
|
-
sys.exit(4)
|
101
|
-
for status in statuses:
|
102
|
-
if status != 0:
|
103
|
-
sys.exit(5)
|
104
|
-
|
105
|
-
if __name__ == "__main__":
|
106
|
-
opts, args = parse_args()
|
107
|
-
cmdline = " ".join(args)
|
108
|
-
try:
|
109
|
-
hosts = psshutil.read_host_files(opts.host_files,
|
110
|
-
default_user=opts.user)
|
111
|
-
except IOError:
|
112
|
-
_, e, _ = sys.exc_info()
|
113
|
-
sys.stderr.write('Could not open hosts file: %s\n' % e.strerror)
|
114
|
-
sys.exit(1)
|
115
|
-
if opts.host_strings:
|
116
|
-
for s in opts.host_strings:
|
117
|
-
hosts.extend(psshutil.parse_host_string(s, default_user=opts.user))
|
118
|
-
do_pssh(hosts, cmdline, opts)
|