Timeout a command efficiently and capture output to a variable in bash script

六月ゝ 毕业季﹏ 提交于 2019-12-24 01:15:01

问题


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:


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
)


来源:https://stackoverflow.com/questions/17382626/timeout-a-command-efficiently-and-capture-output-to-a-variable-in-bash-script

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!