【问题标题】:Timeout a command efficiently and capture output to a variable in bash script有效地超时命令并将输出捕获到 bash 脚本中的变量
【发布时间】:2013-06-29 17:01:58
【问题描述】:

我需要在 bash 脚本中运行命令并在运行时间过长时将其终止。我还需要将所有输出捕获到一个变量中。如果命令首先完成,我需要释放/终止看门狗进程(例如睡眠),因为我可能会运行此类命令的列表。

不幸的是,我无法使用“超时”命令,否则我可以这样做:

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

并检查退出代码 124 以查看是否有超时。

因此我选择的解决方案是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

很遗憾,以下内容没有捕获到 $output 的任何内容:

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

我可以将输出转储到文件中,然后像这样将其加载到变量中,但我宁愿不使用文件:

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

我的问题:有没有更好的方法?理想情况下在不使用文件的情况下也将 stderr 捕获到另一个变量?

【问题讨论】:

    标签: linux bash timeout


    【解决方案1】:

    幸运的是,$() 表示法允许多个命令,因此您可以这样做:

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

    您也可以使用常规的() 对命令进行分组,然后重定向它们的所有输出。可以使用2>&1 将stderr 重定向到stdout,所以你最终会得到这个:

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

    【讨论】:

    • 分组使用大括号{...},而不是括号。
    • @gniourf_gniourf:花括号也可以,但圆括号也可以。
    • @gniourf_gniourf 酷,我不知道。我认为它们是相同的,唯一的区别是我们必须在结束波浪形括号之前放置一个;。好东西。
    • @gniourf_gniourf:在这种情况下,子shell 似乎是合适的,因为不需要保留用于实现超时功能的变量。有些人可能会认为使用 subshel​​l 效率较低,但这是另一个问题。
    猜你喜欢
    • 2012-04-03
    • 1970-01-01
    • 2018-10-01
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    相关资源
    最近更新 更多