-
Notifications
You must be signed in to change notification settings - Fork 2
/
pssh.sh
executable file
·110 lines (87 loc) · 2.52 KB
/
pssh.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/bin/bash
parallel_opts='--no-notice --progress -P 0'
ssh_opts='-o ConnectTimeout=30 -o StrictHostKeyChecking=no -o BatchMode=yes -x'
tag_str='[{}] '
tag_cmd="sed -e 's/^/${tag_str}/'"
usage="Usage: $(basename ${0}) [-nh] [-f HOSTLIST_FILE] [-l LOGFILE] [-s SSH_OPTIONS]
[-p PARALLEL_OPTIONS] COMMAND ...
Runs COMMAND over SSH on all given hosts in parallel.
Requires GNU Parallel.
The string '{}' in COMMAND will be replaced with the hostname when
COMMAND is run. Other template strings are available as well. See the
GNU Parallel man page for more info.
-f HOSTLIST_FILE
Specifies a file containing a list of hostnames to run commands on
over SSH. One hostname per line. If this option is not provided,
hostnames are read from stdin instead.
-l LOGFILE
Specifies a file to write log output. If not provided, logs are
written to stdout. Diagnostic information will always be written to
stderr regardless of whether logs are written to stdout or a logfile.
-s SSH_OPTIONS
Options to pass on to the SSH command. If not provided, defaults
to:
$ssh_opts
-p PARALLEL_OPTIONS
Options to pass on to the parallel command. If not provided,
defaults to:
$parallel_opts
-n
Do not append a tag to the beginning of log output. If this flag
is not given, then every log line will be prefixed with the string
\"[hostname] \" to make it easier to tell what lines in the output
came from which host.
-h, --help
Show this help output.
"
hosts_file=""
logfile=""
tag="yes"
help () {
echo "$usage"
exit 2
}
if [[ "$@" == "--help" ]]; then
help
fi
while getopts :f:l:s:p:nh opt; do
case $opt in
f)
hosts_file="${OPTARG}"
;;
l)
logfile="${OPTARG}"
;;
s)
ssh_opts="${OPTARG}"
;;
p)
parallel_opts="${OPTARG}"
;;
n)
tag="no"
;;
h)
help
;;
\?)
echo "Invalid option: -$OPTARG" >&2
help
;;
esac
done
shift $((OPTIND-1))
cmd="$@"
ssh_cmd="{ ssh ${ssh_opts} {} $(printf "%q" "${cmd}"); } 2>&1"
if [[ "$tag" = "yes" ]]; then
ssh_cmd="${ssh_cmd} | ${tag_cmd}"
fi
hostlist=""
while read line; do
hostlist="$hostlist $line"
done < "${hosts_file:-/proc/${$}/fd/0}"
parallel_cmd="parallel ${parallel_opts} $(printf "%q" "${ssh_cmd}") ::: ${hostlist}"
if [[ -n "$logfile" ]]; then
parallel_cmd="$parallel_cmd > $logfile"
fi
eval "$parallel_cmd"