2

I need to run a command and kill it when running too long, in a bash script. I also need to capture all output to a variable. If the command finishes first, I need to release/kill the watchdog process (e.g. sleep) because I may run a list of such commands.

Unfortunately the "timeout" command is not available to me, othervise I could do something like this:

output=`timeout -s 9 $TIMEOUT my-command`

and check for the exit code 124 to see if there was a timeout.

Therefore my solution of choice is by @Dmitry to a similar question:

( my_command ) & pid=$!
( sleep $TIMEOUT && kill -HUP $pid ) 2>/dev/null & watcher=$!
wait $pid 2>/dev/null && pkill -HUP -P $watcher

Unfortunately the following does not capture anything to the $output:

( output=`my_command` ) & pid=$!

I could dump the output to a file and then load it in the variable like this, but I'd rather do without files:

( `my_command >$outfile` ) & pid=$!
...
output=`cat $outfile`
rm -f $outfile

My question: is there a better way? Ideally capturing the stderr as well to another variable without using files?

1 Answer 1

1

Fortunately, the $() notation allows for multiple commands, so you can do this:

output=$(
    ( my_command ) & pid=$!
    ( sleep $TIMEOUT && kill -HUP $pid ) 2>/dev/null & watcher=$!
    wait $pid 2>/dev/null && pkill -HUP -P $watcher
)

You can also use regular () to group commands and then redirect all their output. Redirecting stderr to stdout can be done using 2>&1, so you end up with this:

output=$(
    (
        ( my_command ) & pid=$!
        ( sleep $TIMEOUT && kill -HUP $pid ) 2>/dev/null & watcher=$!
        wait $pid 2>/dev/null && pkill -HUP -P $watcher
    ) 2>&1
)
Sign up to request clarification or add additional context in comments.

11 Comments

Grouping is done with curly brackets {...}, not parentheses.
@gniourf_gniourf: curly braces may work as well, but parentheses do work.
Parentheses are for subshells. Please see the Grouping Commands section in the bash reference manual
@gniourf_gniourf Cool, I didn't know that. I thought they were the same with the only difference that we had to place a ; before end squiggly bracket. Good stuff.
@gniourf_gniourf: A subshell seems appropriate in this case since there's no need to keep the variables that were used for implementing the timeout functionality. Some may argue it is less efficient to use a subshell, but that's another issue.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.