Sometimes you may want to kill a command if it has been running for more than a specific time limit. For example, a shell script connecting to a network resource may hang for a long period of time if the resource is unavailable and it would be desirable to kill it and send out an alert.
This post describes different ways of running commands with time limits.
1) GNU coreutils timeout
command
The easiest way to run a command with a time limit is by using the timeout
command from GNU coreutils. For example, to run a command with a timeout of 2 minutes:
$ timeout 2m /path/to/command with args $ echo $? 124If the command has not completed within the specified time limit, the
timeout
utility will kill it (by sending it a TERM signal) and then exit with status 124.
2) The expect
command
Another way to run a command with a timeout is by using expect
as shown below:
$ expect -c " set echo '-noecho'; set timeout 10; spawn -noecho /path/to/command with args; expect timeout { exit 124 } eof { exit 0 }" $ echo $? 124In the example above, the timeout is set to 10 seconds and
expect
will exit with a status of 124 when the command exceeds this time limit. Otherwise, it will exit with a status of 0. Unfortunately, you lose the exit code of the command you are running.
3) Using a custom timeout script
If you cannot use the two approaches above, you can write your own timeout script. Mine is shown below. It first starts a "watchdog" process which keeps checking to see if the command is running by executing kill -0
periodically. If it is still running after the time limit has been exceeded, the watchdog kills it.
#!/bin/bash while getopts "t:" opt; do case "$opt" in t) timeout=$OPTARG ;; esac done shift $((OPTIND-1)) start_watchdog(){ timeout="$1" (( i = timeout )) while (( i > 0 )) do kill -0 $$ || exit 0 sleep 1 (( i -= 1 )) done echo "killing process after timeout of $timeout seconds" kill $$ } start_watchdog "$timeout" 2>/dev/null & exec "$@"Example:
$ timeout.sh -t 2 sleep 5 killing process after timeout of 2 seconds Terminated