#!/bin/sh # # Control script for the remote execution jobs. # # The initial script calls `$CONTROL_SCRIPT init-script-finish` once the original script exits. # In automatic mode, the exit code is sent back to the proxy on `init-script-finish`. # # What the script provides is also a manual mode, where the author of the rex script can take # full control of the job lifecycle. This allows keeping the marked as running even when # the initial script finishes. # # The manual mode is turned on by calling `$CONTROL_SCRIPT manual-control`. After calling this, # one can call `echo message | $CONTROL_SCRIPT update` to send output to the remote execution jobs # and `$CONTROL_SCRIPT finish 0` once finished (with 0 as exit code) to send output to the remote execution jobs # and `$CONTROL_SCRIPT finish 0` once finished (with 0 as exit code) BASE_DIR=“$(dirname ”$(readlink -f “$0”)“)”
if ! command -v curl >/dev/null; then
echo 'curl is required' >&2 exit 1
fi
# send the callback data to proxy update() {
"$BASE_DIR/retrieve.sh" push_update
}
# wait for named pipe $1 to retrieve data. If $2 is provided, it serves as timeout # in seconds on how long to wait when reading. wait_for_pipe() {
pipe_path=$1
if [ -n "$2" ]; then
timeout="-t $2"
fi
if read $timeout <>"$pipe_path"; then
rm "$pipe_path"
return 0
else
return 1
fi
}
# function run in background, when receiving update data via STDIN. periodic_update() {
interval=1
# reading some data from periodic_update_control signals we're done
while ! wait_for_pipe "$BASE_DIR/periodic_update_control" "$interval"; do
update
done
# one more update before we finish
update
# signal the main process that we are finished
echo > "$BASE_DIR/periodic_update_finished"
}
# signal the periodic_update process that the main process is finishing periodic_update_finish() {
if [ -e "$BASE_DIR/periodic_update_control" ]; then echo > "$BASE_DIR/periodic_update_control" fi
}
ACTION=${1:-finish}
case “$ACTION” in
init-script-finish)
if ! [ -e "$BASE_DIR/manual_mode" ]; then
# make the exit code of initialization script the exit code of the whole job
cp init_exit_code exit_code
update
fi
;;
finish)
# take exit code passed via the command line, with fallback
# to the exit code of the initialization script
exit_code=${2:-$(cat "$BASE_DIR/init_exit_code")}
echo $exit_code > "$BASE_DIR/exit_code"
update
if [ -e "$BASE_DIR/manual_mode" ]; then
rm "$BASE_DIR/manual_mode"
fi
;;
update)
# read data from input when redirected though a pipe
if ! [ -t 0 ]; then
# couple of named pipes to coordinate the main process with the periodic_update
mkfifo "$BASE_DIR/periodic_update_control"
mkfifo "$BASE_DIR/periodic_update_finished"
trap "periodic_update_finish" EXIT
# run periodic update as separate process to keep sending updates in output to server
periodic_update &
# redirect the input into output
tee -a "$BASE_DIR/output"
periodic_update_finish
# ensure the periodic update finished before we return
wait_for_pipe "$BASE_DIR/periodic_update_finished"
else
update
fi
;;
# mark the script to be in manual mode: this means the script author needs to use `update` and `finish`
# commands to send output to the remote execution job or mark it as finished.
manual-mode)
touch "$BASE_DIR/manual_mode"
;;
*)
echo "Unknown action $ACTION"
exit 1
;;
esac