Save this as
tkill (make it executable and adjust your
PATH if needed):
trap "exit 143" SIGTERM && kill -- -$$
trap _terminate_children SIGINT SIGTERM
eval $@ | tee >(while :; do
read -t "$tout"
case $? in
0) : ;;
1) break ;;
*) _terminate_children ;;
tkill 30 some_command
The first argument (
30 here) is the timeout in seconds.
some_command to generate text (not binary) output.
stdout of the given command. To include
stderr redirect it like in the last advanced example below.
These are valid examples:
tkill 9 foo -option value
tkill 9 "foo -option value" # equivalent to the above
tkill 5 "foo | bar"
tkill 5 'foo | bar'
tkill 5 'foo | bar | baz' # tkill monitors baz
tkill 5 'foo | bar' | baz # baz reads from tkill
tkill 3 "foo; bar"
tkill 6 "foo && bar || baz"
tkill 7 "some_command 2>&1"
Use Bash syntax in these quotes.
some_command exits by itself then its exit status will be reused as the exit status of
tkill 5 true returns
tkill 5 false returns
tkill 5 "true; false" returns
- If the given timeout expires or
tkill gets interrupted by
SIGTERM then the exit status will be
Fragments of code explained
eval makes the advanced examples possible.
tee allows us to analyze
stdin while still passing a copy of it to
read -t is responsible for applying the timeout, its exit status is used to determine what to do next.
- Command(s) being monitored are killed when needed with this solution.
- Exit status of monitored command(s) is retrieved with this solution.