kopia lustrzana https://github.com/modem7/docker-borgmatic
255 wiersze
5.9 KiB
Bash
255 wiersze
5.9 KiB
Bash
#!/bin/sh
|
|
|
|
cmdname="${0##*/}"
|
|
|
|
VERSION=0.0.3
|
|
|
|
echoto() {
|
|
# print to stderr or to stdout
|
|
out=$1
|
|
shift 1
|
|
|
|
if ([ "${out}" -eq 2 ]); then
|
|
printf "$@" >&2
|
|
else
|
|
# stdout can be silenced only
|
|
if [ "${QUIET}" -eq 0 ]; then
|
|
printf "$@"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
progress() {
|
|
if ([ "${PROGRESS}" -eq 1 ]); then
|
|
echoto 1 "."
|
|
fi
|
|
}
|
|
|
|
usage() {
|
|
# (TODO) -F, --format-progress=FORMAT set FORMAT for progress, available: DOTS, PROGRESSBAR (default is DOTS)
|
|
OUTPUT=`cat <<EOF
|
|
Usage: $cmdname [OPTION]... [COMMAND]
|
|
wtfc (WaiT For The Command) waits for the COMMAND provided as the last argument or via standard input to return within timeout with expected exit status.
|
|
|
|
Functional arguments:
|
|
-I, --interval=SECONDS set the check interval to SECONDS (default is 1)
|
|
-S, --status=NUMBER set the expected COMMAND exit status to NUMBER (default is 0)
|
|
-T, --timeout=SECONDS set the timeout to SECONDS (0 for no timeout, default is 1)
|
|
|
|
Logging and info arguments:
|
|
-P, --progress show progress (default is 0)
|
|
-H, --help print this help and exit
|
|
-Q, --quiet be quiet
|
|
-V, --version display the version of wtfc and exit.
|
|
|
|
Examples:
|
|
./wtfc.sh -T 1 -S 0 ls /tmp Waits for 1 second for 'ls /tmp' to execute with exit status 0
|
|
echo "ls /foo/bar" | ./wtfc.sh -T 2 -S 2 Waits for 2 seconds for 'ls /foo/bar' to execute with exit status 2
|
|
EOF
|
|
`
|
|
|
|
# print to stderr (for exit status > 0), otherwise to stdout
|
|
if ([ "$1" -gt 0 ]); then
|
|
echo "${OUTPUT}" >&2
|
|
else
|
|
echo "${OUTPUT}"
|
|
fi
|
|
|
|
exit $1
|
|
}
|
|
|
|
version() {
|
|
echo "wtfc (WaiT For the Command) version: ${VERSION}"
|
|
exit 0
|
|
}
|
|
|
|
wait_for(){
|
|
if [ "${TIMEOUT}" -gt 0 ]; then
|
|
echoto 1 "$cmdname: waiting $TIMEOUT seconds for $CMD\n"
|
|
else
|
|
echoto 1 "$cmdname: waiting without a timeout for $CMD\n"
|
|
fi
|
|
|
|
while :
|
|
do
|
|
eval $CMD >/dev/null 2>&1
|
|
result=$?
|
|
|
|
if ([ "${result}" -eq "${STATUS}" ]); then
|
|
break
|
|
fi
|
|
sleep $INTERVAL
|
|
|
|
progress
|
|
done
|
|
return $result
|
|
}
|
|
|
|
wait_for_wrapper() {
|
|
TIME_START=$(date +%s)
|
|
|
|
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
|
|
if ([ "${QUIET}" -eq 1 ]); then
|
|
eval $TIMEOUT_CMD $TIMEOUT_FLAG $TIMEOUT $0 --quiet --child --status=$STATUS --timeout=$TIMEOUT $CMD &
|
|
else
|
|
eval $TIMEOUT_CMD $TIMEOUT_FLAG $TIMEOUT $0 --child --status=$STATUS --timeout=$TIMEOUT $CMD &
|
|
fi
|
|
PID=$!
|
|
trap "kill -INT -$PID" INT
|
|
|
|
while [ $(($(date +%s)-TIME_START)) -lt "${TIMEOUT}" ]; do
|
|
|
|
eval $CMD >/dev/null 2>&1
|
|
result=$?
|
|
|
|
if ([ "${result}" -eq "${STATUS}" ]); then
|
|
break
|
|
fi
|
|
|
|
sleep $INTERVAL
|
|
|
|
progress
|
|
done
|
|
wait $PID
|
|
RESULT=$?
|
|
return $RESULT
|
|
}
|
|
|
|
# process arguments
|
|
while [ $# -gt 0 ]
|
|
do
|
|
case "$1" in
|
|
--child)
|
|
CHILD=1
|
|
shift 1
|
|
;;
|
|
-H | --help)
|
|
usage 0
|
|
;;
|
|
-I)
|
|
INTERVAL="$2"
|
|
if [ -z "${INTERVAL}" ]; then break; fi
|
|
shift 2
|
|
;;
|
|
--interval=*)
|
|
INTERVAL="${1#*=}"
|
|
shift 1
|
|
;;
|
|
-P | --progress)
|
|
PROGRESS=1
|
|
shift 1
|
|
;;
|
|
-Q | --quiet)
|
|
QUIET=1
|
|
shift 1
|
|
;;
|
|
-S)
|
|
STATUS="$2"
|
|
if [ -z "${STATUS}" ]; then break; fi
|
|
shift 2
|
|
;;
|
|
--status=*)
|
|
STATUS="${1#*=}"
|
|
shift 1
|
|
;;
|
|
-T)
|
|
TIMEOUT="$2"
|
|
if [ -z "${TIMEOUT}" ]; then break; fi
|
|
shift 2
|
|
;;
|
|
--timeout=*)
|
|
TIMEOUT="${1#*=}"
|
|
shift 1
|
|
;;
|
|
-V | --version)
|
|
version
|
|
;;
|
|
-*)
|
|
echoto 2 "Unknown argument: $1"
|
|
usage 1
|
|
;;
|
|
*)
|
|
CMD="$@"
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# read from stdin, if no cmd provided
|
|
if [ -z "${CMD}" ]; then
|
|
read CMD
|
|
fi
|
|
|
|
if [ -z "${CMD}" ]; then
|
|
echoto 2 "Error: you need to provide a COMMAND to test as the last argument or via standard input.\n"
|
|
usage 1
|
|
fi
|
|
|
|
CHILD=${CHILD:-0}
|
|
INTERVAL=${INTERVAL:-1}
|
|
PROGRESS=${PROGRESS:-0}
|
|
QUIET=${QUIET:-0}
|
|
STATUS=${STATUS:-0}
|
|
TIMEOUT=${TIMEOUT:-1}
|
|
|
|
# check to see if timeout is from busybox/alpine => '-t' switch is required or not
|
|
TIMEOUT_TEST="$(timeout 1 sleep 0 2>&1)"
|
|
case "${TIMEOUT_TEST}" in
|
|
timeout:\ can\'t\ execute\ \'1\':*) TIMEOUT_FLAG="-t" ;;
|
|
*) TIMEOUT_FLAG="" ;;
|
|
esac
|
|
|
|
TIMEOUT_TEST="$(timeout ${TIMEOUT_FLAG} 1 sleep 0 2>&1)"
|
|
TIMEOUT_TEST_STATUS="$?"
|
|
|
|
# fallback for osx (uses gtimeout)
|
|
if [ "${TIMEOUT_TEST_STATUS}" -eq 127 ]; then
|
|
TIMEOUT_TEST="$(gtimeout ${TIMEOUT_FLAG} 1 sleep 0 2>&1)"
|
|
TIMEOUT_TEST_STATUS="$?"
|
|
|
|
if [ "${TIMEOUT_TEST_STATUS}" -eq 127 ]; then
|
|
TIMEOUT_TEST="$(gnu-timeout ${TIMEOUT_FLAG} 1 sleep 0 2>&1)"
|
|
TIMEOUT_TEST_STATUS="$?"
|
|
|
|
if [ "${TIMEOUT_TEST_STATUS}" -eq 127 ]; then
|
|
echoto 2 "timeout|gtimeout|gnu-timeout is required by the script, but not found!\n"
|
|
exit 1
|
|
fi
|
|
TIMEOUT_CMD="gnu-timeout"
|
|
else
|
|
TIMEOUT_CMD="gtimeout"
|
|
fi
|
|
else
|
|
TIMEOUT_CMD="timeout"
|
|
fi
|
|
|
|
start_ts=$(date +%s)
|
|
|
|
if [ "${CHILD}" -eq 1 ]; then
|
|
wait_for
|
|
RESULT=$?
|
|
exit $RESULT
|
|
else
|
|
if [ "${TIMEOUT}" -gt 0 ]; then
|
|
wait_for_wrapper
|
|
RESULT=$?
|
|
else
|
|
wait_for
|
|
RESULT=$?
|
|
fi
|
|
fi
|
|
|
|
if [ "${RESULT}" -ne "${STATUS}" ]; then
|
|
echoto 2 "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $CMD to return status: $STATUS (was status: $RESULT)\n"
|
|
if [ "${RESULT}" -eq 0 ]; then
|
|
# exit with 1, inspite the fact original ended with 0 (as we expected non-0)
|
|
exit 1
|
|
else
|
|
exit $RESULT
|
|
fi
|
|
else
|
|
end_ts=$(date +%s)
|
|
echoto 1 "$cmdname: $CMD finished with expected status $RESULT after $((end_ts - start_ts)) seconds\n"
|
|
exit 0
|
|
fi
|