Skip to content

Commit 5aecbcc

Browse files
committed
Add exit status reporting
Attempts to address #1. Exit statuses are captured and written to a temporary location (or optionally a user-specified file). We somewhat arbitrarily return the highest-numbered exit status, with the intent to avoid returning "0" (since that would signal everything worked as expected).
1 parent de77664 commit 5aecbcc

File tree

1 file changed

+34
-8
lines changed

1 file changed

+34
-8
lines changed

bin/dssh

+34-8
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ ssh_opts="-oBatchMode=yes \
3838
-oForwardX11=no \
3939
-oStrictHostkeyChecking=no"
4040

41-
unset color flock footer lockfile header host_list
41+
unset cleanup_files color exitfile flock footer lockfile header host_list
4242
abbrev=false
4343
active_threads=0
4444
delay=0
@@ -88,6 +88,7 @@ Additional options:
8888
* -u username execute commands as 'username'
8989
* -s timeout set how long to wait before timing out (in seconds)
9090
* -t num_threads limit the number of parallel threads (implies -p)
91+
* -x exit_file write the exit status for each host to exit_file
9192
* -y allocate PTY (enables screen-based apps and job control)
9293
9394
EOM
@@ -156,12 +157,13 @@ ssh_host() {
156157
[[ ${exit_code} -eq 255 ]] && error=true
157158

158159
if [[ ${error} == true || ${quiet} == false ]]; then
160+
host_display="${host}"
159161
if [[ ${color} == true ]]; then
160162
c=${def_color}; [[ ${error} == true ]] && c=${err_color}
161-
host=$'\e[0;'${c}'m'"${host}"$'\e[0m'
163+
host_display=$'\e[0;'${c}'m'"${host}"$'\e[0m'
162164
fi
163165

164-
header="-- ${host} --"$'\n'
166+
header="-- ${host_display} --"$'\n'
165167
footer=$'\n'
166168
output="${header}${output}${footer}"
167169
fi
@@ -175,7 +177,12 @@ ssh_host() {
175177
fi
176178

177179
# acquire lock and print output
178-
( lock; kill -s SIGUSR1 $$; echo -n "${output}" ) 40> "${lockfile}"
180+
(
181+
lock
182+
kill -s SIGUSR1 $$
183+
echo -n "${output}"
184+
echo -e "${exit_code}\t${host}" >> "${exitfile}"
185+
) 40> "${lockfile}"
179186
}
180187

181188
ssh_live() {
@@ -202,16 +209,21 @@ ssh_live() {
202209
ssh ${ssh_opts} ${host} ${@} 2>&1 | while read line; do
203210
echo "${hname}${line}"
204211
done
212+
exit_code=${PIPESTATUS[0]}
205213

206214
if [[ "${delay}" -gt 0 ]]; then
207215
sleep "${delay}"
208216
fi
209217

210218
# notify our 'thread pool' that the next task can run
211-
( lock; kill -s SIGUSR1 $$ ) 40> "${lockfile}"
219+
(
220+
lock
221+
kill -s SIGUSR1 $$
222+
echo -e "${exit_code}\t${host}" >> "${exitfile}"
223+
) 40> "${lockfile}"
212224
}
213225

214-
while getopts "aAcd:ef:i:jl:o:pqu:s:t:y" flag; do
226+
while getopts "aAcd:ef:i:jl:o:pqu:s:t:x:y" flag; do
215227
case ${flag} in
216228
a) cmd="${cmd_live}"; abbrev=false ;;
217229
A) cmd="${cmd_live}"; abbrev=true ;;
@@ -230,6 +242,7 @@ while getopts "aAcd:ef:i:jl:o:pqu:s:t:y" flag; do
230242
u) ssh_opts="${ssh_opts} -l${OPTARG}" ;;
231243
s) ssh_opts="${ssh_opts} -oConnectTimeout=${OPTARG}" ;;
232244
t) parallel=true; max_threads=${OPTARG} ;;
245+
x) exitfile="${OPTARG}" ;;
233246
y) ssh_opts="${ssh_opts} -t -t" ;;
234247
?) error_die ;;
235248
esac
@@ -271,9 +284,17 @@ if [[ ${parallel} == false ]] ; then
271284
max_threads=1
272285
fi
273286

274-
lockfile="${TMPDIR:-/tmp}/dssh.$$.$RANDOM.lock"
287+
lock_base="${TMPDIR:-/tmp}/dssh.$$.$RANDOM"
288+
lockfile="${lock_base}.lock"
289+
cleanup_files="${lockfile}"
275290
touch "${lockfile}"
276-
trap 'rm -f ${lockfile}' EXIT
291+
292+
if [[ -z "${exitfile}" ]]; then
293+
exitfile="${lock_base}.exit"
294+
cleanup_files="${cleanup_files} ${exitfile}"
295+
fi
296+
297+
trap 'rm -f ${cleanup_files}' EXIT
277298

278299
set -f # Temporarily disable pathname expansion
279300
for host in ${hosts}; do
@@ -299,3 +320,8 @@ done
299320
set +f
300321

301322
until wait; do :; done
323+
324+
status="$(sort -n "${exitfile}" 2>/dev/null | tail -n 1 | cut -f1)" 2> /dev/null
325+
if [[ -n "${status}" ]]; then
326+
exit "${status}"
327+
fi

0 commit comments

Comments
 (0)