#!/bin/sh
if ! pgrep –help 2>/dev/null >/dev/null; then
echo DONE 1 echo "pgrep is required" >&2 exit 1
fi
BASE_DIR=“$(dirname ”$(readlink -f “$0”)“)”
# load the data required for generating the callback . “$BASE_DIR/env.sh” URL_PREFIX=“$CALLBACK_HOST/dynflow/tasks/$TASK_ID” AUTH=“$TASK_ID:$OTP” CURL=“curl –silent –show-error –fail –max-time 10”
MY_LOCK_FILE=“$BASE_DIR/retrieve_lock.$$” MY_PID=$$ echo $MY_PID >“$MY_LOCK_FILE” LOCK_FILE=“$BASE_DIR/retrieve_lock” TMP_OUTPUT_FILE=“$BASE_DIR/tmp_output”
RUN_TIMEOUT=30 # for how long can the script hold the lock WAIT_TIMEOUT=60 # for how long the script is trying to acquire the lock START_TIME=$(date +%s)
fail() {
echo RUNNING echo "$1" exit 1
}
acquire_lock() {
# try to acquire lock by creating the file (ln should be atomic an fail in case # another process succeeded first). We also check the content of the lock file, # in case our process won when competing over the lock while invalidating # the lock on timeout. ln "$MY_LOCK_FILE" "$LOCK_FILE" 2>/dev/null || [ "$(head -n1 "$LOCK_FILE")" = "$MY_PID" ] return $?
}
# acquiring the lock before proceeding, to ensure only one instance of the script is running while ! acquire_lock; do
# we failed to create retrieve_lock - assuming there is already another retrieve script running current_pid=$(head -n1 "$LOCK_FILE") if [ -z "$current_pid" ]; then continue fi # check whether the lock is not too old (compared to $RUN_TIMEOUT) and try to kill # if it is, so that we don't have a stalled processes here lock_lines_count=$(wc -l < "$LOCK_FILE") current_lock_time=$(stat --format "%Y" "$LOCK_FILE") current_time=$(date +%s) if [ "$(( current_time - START_TIME ))" -gt "$WAIT_TIMEOUT" ]; then # We were waiting for the lock for too long - just give up fail "Wait time exceeded $WAIT_TIMEOUT" elif [ "$(( current_time - current_lock_time ))" -gt "$RUN_TIMEOUT" ]; then # The previous lock it hold for too long - re-acquiring procedure if [ "$lock_lines_count" -gt 1 ]; then # there were multiple processes waiting for lock without resolution # longer than the $RUN_TIMEOUT - we reset the lock file and let processes # to compete echo "RETRY" > "$LOCK_FILE" fi if [ "$current_pid" != "RETRY" ]; then # try to kill the currently stalled process kill -9 "$current_pid" 2>/dev/null fi # try to add our process as one candidate echo $MY_PID >> "$LOCK_FILE" if [ "$( head -n2 "$LOCK_FILE" | tail -n1 )" = "$MY_PID" ]; then # our process won the competition for the new lock: it is the first pid # after the original one in the lock file - take ownership of the lock # next iteration only this process will get through echo $MY_PID >"$LOCK_FILE" fi else # still waiting for the original owner to finish sleep 1 fi
done
release_lock() {
rm "$MY_LOCK_FILE" rm "$LOCK_FILE"
} # ensure the release the lock at exit trap “release_lock” EXIT
# make sure we clear previous tmp output file if [ -e “$TMP_OUTPUT_FILE” ]; then
rm "$TMP_OUTPUT_FILE"
fi
pid=$(cat “$BASE_DIR/pid”)
- -f “$BASE_DIR/position”
-
|| echo 1 > “$BASE_DIR/position”
position=$(cat “$BASE_DIR/position”)
prepare_output() {
if [ -e "$BASE_DIR/manual_mode" ] || ([ -n "$pid" ] && pgrep -P "$pid" >/dev/null 2>&1); then echo RUNNING else echo "DONE $(cat "$BASE_DIR/exit_code" 2>/dev/null)" fi [ -f "$BASE_DIR/output" ] || exit 0 tail --bytes "+${position}" "$BASE_DIR/output" > "$TMP_OUTPUT_FILE" cat "$TMP_OUTPUT_FILE"
}
# prepare the callback payload payload() {
if [ -n "$1" ]; then exit_code="$1" else exit_code=null fi if [ -e "$BASE_DIR/manual_mode" ]; then manual_mode=true output=$(prepare_output | base64 -w0) else manual_mode=false fi echo "{ \"exit_code\": $exit_code,"\ " \"step_id\": \"$STEP_ID\","\ " \"manual_mode\": $manual_mode,"\ " \"output\": \"$output\" }"
}
if [ “$1” = “push_update” ]; then
if [ -e "$BASE_DIR/exit_code" ]; then exit_code="$(cat "$BASE_DIR/exit_code")" action="done" else exit_code="" action="update" fi $CURL -X POST -d "$(payload $exit_code)" -u "$AUTH" "$URL_PREFIX"/$action 2>>"$BASE_DIR/curl_stderr" success=$?
else
prepare_output success=$?
fi
if [ “$success” = 0 ] && [ -e “$TMP_OUTPUT_FILE” ]; then
# in case the retrieval was successful, move the position of the cursor to be read next time bytes=$(wc --bytes < "$TMP_OUTPUT_FILE") expr "${position}" + "${bytes}" > "$BASE_DIR/position"
fi