#!/usr/bin/env sh # # Compare a command exit status to some given number(s) for a period of time. CMD_NAME="${0##*/}" CMD="" STATUS=0 TIME=10 TIME_START=0 QUIET=0 EXIT_STATUS=1 usage() { cat << EOF >&2 Usage: ${CMD_NAME} [-c 'COMMAND'] ${CMD_NAME} [OPTION]... [-c 'COMMAND'] ${CMD_NAME} [-c 'COMMAND'] [OPTION]... ${CMD_NAME} compares a command exit status to some given number(s) for a period of time. If comparison is successfully ${CMD_NAME} returns 0, otherwise 1. Example: ${CMD_NAME} -c 'echo > /dev/tcp/127.0.0.1/5432' ${CMD_NAME} -s 0 57 -c 'curl 127.0.0.1:5432' ${CMD_NAME} -c 'nc -z 127.0.0.1 5432' -s 0 -t 20 -q Options: -c, --command ['COMMAND'] execute a COMMAND. -s, --status [NUMBER]... target exit status of COMMAND, default 0. -t, --time [NUMBER] max time to wait in seconds, default 10. -q, --quiet do not make any output, default false. --help display this help. Notice that quotes are needed after -c/--command for multi-argument COMMANDs. Specifying a same OPTION more than once overrides the previews. So "${CMD_NAME} -c 'nothing' -c 'curl 127.0.0.1:5432'" will be the same as "${CMD_NAME} -c 'curl 127.0.0.1:5432'". It does not apply to option -q/--quiet. EOF exit 0 } output() { if [ "${QUIET}" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi } process_command() { while [ "$#" -gt 0 ]; do case "$1" in -c | --command) # allow one shift when no arguments if [ -n "$2" ]; then CMD="$2" shift 1 fi shift 1 ;; -s | --status) # ensure that a number is provided if ([ "$2" -eq "$2" ]) >/dev/null 2>&1; then unset STATUS # ensure that a number is provided while ([ "$2" -eq "$2" ]) >/dev/null 2>&1; do if [ -z "${STATUS}" ]; then STATUS="$2" shift 1 else STATUS="${STATUS} $2" shift 1 fi done fi shift 1 ;; -t | --time) # ensure that a number is provided if ([ "$2" -eq "$2" ]) >/dev/null 2>&1; then TIME="$2" shift 1 fi shift 1 ;; -q | --quiet) QUIET=1 shift 1 ;; --help) usage ;; *) output "Unknown argument: $1" output "Try '${CMD_NAME} --help' for more information." exit "${EXIT_STATUS}" ;; esac done if [ -z "${CMD}" ]; then output "Missing command: -c, --command ['COMMAND']" output "Try '${CMD_NAME} --help' for more information." exit "${EXIT_STATUS}" fi } main() { message="failed" process_command "$@" TIME_START=$(date +%s) while [ $(($(date +%s)-TIME_START)) -lt "${TIME}" ]; do ($CMD) >/dev/null 2>&1 & pid="$!" # while both ps and time are running sleep 1s while kill -0 "${pid}" >/dev/null 2>&1 && [ $(($(date +%s)-TIME_START)) -lt "${TIME}" ]; do sleep 1 done # gets CMD status kill "${pid}" >/dev/null 2>&1 wait "${pid}" >/dev/null 2>&1 cmd_exit_status="$?" # looks for equlity in CMD exit status and one of the given status for i in $STATUS; do if ([ "${cmd_exit_status}" -eq "${i}" ]) >/dev/null 2>&1; then message="finished successfully" EXIT_STATUS=0 break 2 fi done done output "${CMD_NAME} ${message} after $(($(date +%s)-TIME_START)) second(s)." output "cmd: ${CMD}" output "target exit status: ${STATUS}" output "exited status: ${cmd_exit_status}" exit "${EXIT_STATUS}" } main "$@"