#!/bin/sh usage() { printf "Usage: %s [-v] [-h] [-t TIMEOUT] [-c COMMAND]\n\n" "$0" } help() { cat << EOH SYNOPSIS $0 [-v] [-h] [-t TIMEOUT] [-c COMMAND] DESCRIPTION \`Timeout\` executes a command until the timeout is over. When the command is finished before the timeout then the exit code is \`0\` else it's \`1\`. OPTIONS -h Show this help -v Display the command output (stderr) -c COMMAND The command to execute \`COMMAND=... $0\` works to. -t TIMEOUT The timeout in seconds (default: 10) \`TIMEOUT=... $0\` works to. EOH } on_interrupt() { print "Process aborted!\n" exit 130 } create_script() { printf "#!/bin/sh\n%s\n" "$1" > "$2" chmod +x "$SCRIPT_FILE" } run_script() { if [ "$2" -eq 0 ]; then "$SCRIPT_FILE" >/dev/null 2>&1 & else "$SCRIPT_FILE" >&2 & fi printf "%d" $! } stop_delete_script() { kill -9 "$1" rm -f "$2" } check_pid() { PID=$1 LOOP=$2 for _ in $(seq 1 "$((LOOP*2))"); do test -d "/proc/$PID/" && sleep 0.5 || STATUS=0 done printf "%d" ${STATUS:-1} } main() { while getopts "ht:c:v" option; do case "${option}" in h) help; exit 0;; t) TIMEOUT="$OPTARG";; c) COMMAND="$OPTARG";; v) VERBOSE=1;; *) usage; exit 1;; esac done TIMEOUT="${TIMEOUT:-10}" VERBOSE="${VERBOSE:-0}" if [ -z "$COMMAND" ]; then printf "Command is required!\n" exit 1 fi SCRIPT_FILE="$(mktemp)" create_script "$COMMAND" "$SCRIPT_FILE" SCRIPT_PID=$(run_script "$SCRIPT_FILE" "$VERBOSE") EXIT_STATUS=$(check_pid "$SCRIPT_PID" "$TIMEOUT") stop_delete_script "$SCRIPT_PID" "$SCRIPT_FILE" exit "$EXIT_STATUS" } trap on_interrupt INT main "$@"