|
@@ -1,7 +1,12 @@
|
|
|
#!/bin/sh
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
readonly DEFAULT_OUT_FMT="%s.out"
|
|
readonly DEFAULT_OUT_FMT="%s.out"
|
|
|
-readonly CMD_FEED="$(mktemp -u distributer-XXX.fifo)"
|
|
|
|
|
|
|
+readonly CMD_FEED="$(mktemp -u /tmp/distributer-XXX.fifo)"
|
|
|
|
|
+readonly LOCK="$CMD_FEED.lock"
|
|
|
|
|
+readonly LOCK_TIMEOUT="1"
|
|
|
|
|
+readonly PROC_BUFFER=10
|
|
|
|
|
+readonly MAX_PROCS=$(expr $(ulimit -u) / 3 - $PROC_BUFFER)
|
|
|
|
|
+
|
|
|
readonly CONF_LIST="$1"
|
|
readonly CONF_LIST="$1"
|
|
|
readonly SERVER_LIST="$2"
|
|
readonly SERVER_LIST="$2"
|
|
|
readonly OUT_FMT="${3:-$DEFAULT_OUT_FMT}"
|
|
readonly OUT_FMT="${3:-$DEFAULT_OUT_FMT}"
|
|
@@ -20,7 +25,7 @@ help() {
|
|
|
printf " server_list: A text file containing a list of servers to\n" >&2
|
|
printf " server_list: A text file containing a list of servers to\n" >&2
|
|
|
printf " connect to and run commands on.\n" >&2
|
|
printf " connect to and run commands on.\n" >&2
|
|
|
printf " out_file_fmt: File name format to write the output of each\n" >&2
|
|
printf " out_file_fmt: File name format to write the output of each\n" >&2
|
|
|
- printf " command to (default: $DEFAULT_OUT_FMT).\n\n" >&2
|
|
|
|
|
|
|
+ printf " command to (default: %s).\n\n" "$DEFAULT_OUT_FMT" >&2
|
|
|
printf "All commands will be allocated to the first available server.\n" >&2
|
|
printf "All commands will be allocated to the first available server.\n" >&2
|
|
|
printf "Each command must be valid on every server.\n" >&2
|
|
printf "Each command must be valid on every server.\n" >&2
|
|
|
printf "The output will be saved to a text file on the remote systems.\n" >&2
|
|
printf "The output will be saved to a text file on the remote systems.\n" >&2
|
|
@@ -38,13 +43,15 @@ run_server() {
|
|
|
loop="/tmp/$(basename $CMD_FEED .fifo)-$server.fifo"
|
|
loop="/tmp/$(basename $CMD_FEED .fifo)-$server.fifo"
|
|
|
mkfifo "$loop"
|
|
mkfifo "$loop"
|
|
|
trap "clean_server $loop" 2 15
|
|
trap "clean_server $loop" 2 15
|
|
|
- while read cmd; do
|
|
|
|
|
|
|
+ while lockfile -$LOCK_TIMEOUT "$LOCK"; read cmd; do
|
|
|
|
|
+ rm -f "$LOCK"
|
|
|
cmd_sanitized="$(echo "$cmd" | sed "$S_SPACE;$R_DASH;$S_QUOTE")"
|
|
cmd_sanitized="$(echo "$cmd" | sed "$S_SPACE;$R_DASH;$S_QUOTE")"
|
|
|
out_file="$(printf "$OUT_FMT" "$cmd_sanitized")"
|
|
out_file="$(printf "$OUT_FMT" "$cmd_sanitized")"
|
|
|
printf "$server: $cmd\n" >&2
|
|
printf "$server: $cmd\n" >&2
|
|
|
printf "$cmd > $out_file\necho\n"
|
|
printf "$cmd > $out_file\necho\n"
|
|
|
read line < "$loop" > /dev/null # Block until command completes
|
|
read line < "$loop" > /dev/null # Block until command completes
|
|
|
done | ssh -oBatchMode=yes -oStrictHostKeyChecking=no "$server" "sh" > "$loop"
|
|
done | ssh -oBatchMode=yes -oStrictHostKeyChecking=no "$server" "sh" > "$loop"
|
|
|
|
|
+ rm -f "$LOCK"
|
|
|
clean_server "$loop"
|
|
clean_server "$loop"
|
|
|
echo "Server '$server' finished!" >&2
|
|
echo "Server '$server' finished!" >&2
|
|
|
}
|
|
}
|
|
@@ -54,20 +61,20 @@ clean_up() {
|
|
|
pkill -P $pid
|
|
pkill -P $pid
|
|
|
done
|
|
done
|
|
|
rm "$CMD_FEED"
|
|
rm "$CMD_FEED"
|
|
|
|
|
+ [ -e "$LOCK" ] && rm -f "$LOCK"
|
|
|
exit 2
|
|
exit 2
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
main() {
|
|
main() {
|
|
|
mkfifo "$CMD_FEED"
|
|
mkfifo "$CMD_FEED"
|
|
|
trap clean_up 2 15
|
|
trap clean_up 2 15
|
|
|
- sed '/^[[:space:]]*$/d' "$CONF_LIST" > "$CMD_FEED" &
|
|
|
|
|
|
|
+ cat "$CONF_LIST" | sed '/^[[:space:]]*$/d' > "$CMD_FEED" &
|
|
|
pids=""
|
|
pids=""
|
|
|
- for server in $(cat $SERVER_LIST); do
|
|
|
|
|
|
|
+ for server in $(head -n$MAX_PROCS "$SERVER_LIST"); do
|
|
|
run_server "$server" < "$CMD_FEED" > /dev/null &
|
|
run_server "$server" < "$CMD_FEED" > /dev/null &
|
|
|
- pids="$pids $!"
|
|
|
|
|
done
|
|
done
|
|
|
- for pid in $pids; do
|
|
|
|
|
- wait $pids
|
|
|
|
|
|
|
+ for pid in $(pgrep -P $$); do
|
|
|
|
|
+ wait $pid
|
|
|
done
|
|
done
|
|
|
clean_up
|
|
clean_up
|
|
|
echo "All jobs finished!"
|
|
echo "All jobs finished!"
|