在脚本中使用`until`和`/ usr/bin/timeout`

kno*_*cte 6 bash loops timeout while-loop

我想在bash脚本中执行一个大约需要1分钟才能完成的命令.但是,有时这个命令会挂起,所以我想在循环中使用/ usr/bin/timeout直到它工作.

如果我使用timeout 300 mycommand myarg1它,它可以工作,但如果我在下面的循环中使用它在bash中,它不打印任何东西(甚至不是我的命令打印的典型输出)并且它挂起!:

until timeout 300 mycommand myarg
do
    echo "The command timed out, trying again..."
done
Run Code Online (Sandbox Code Playgroud)

我的bash版本:

$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
Run Code Online (Sandbox Code Playgroud)

我的超时版本:

$ timeout --version
timeout (GNU coreutils) 8.25
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Run Code Online (Sandbox Code Playgroud)

(标准Ubuntu16.04)

WLG*_*Gfx 0

我最近必须找到一种解决方案来终止无法完成的进程。这就是我设法想出的:

(mycommand args) & pid=$!
sleep 1000 && kill -INT $pid
Run Code Online (Sandbox Code Playgroud)

应该是不言自明的。运行您的命令并获取进程 ID。超时后将其杀死。

我的具体用途是扫描 DVB-S:

(w_scan -a 7 -E 0 -f s -c $1 -s $2 -o 7 -x >$tunefile) & pid=$!
sleep 1500 && kill -INT $pid
Run Code Online (Sandbox Code Playgroud)

w_scan 命令永远不会完成,并且会永远循环扫描相同的频率。

编辑:您可以检查 pid 是否仍在运行:这至少允许您的脚本采取相应的行动。

if ps -p $id > /dev/null
then 
    : active
else
    : inactive
fi
Run Code Online (Sandbox Code Playgroud)

EDIT2:我刚刚使用 ffmpeg 运行了一个快速脚本,将一种格式转换为另一种格式。我的测试将 mkv(2Gb 文件)转换为 mp4。这通常需要很长时间,但我想让它在 10 秒内运行,然后退出。

虽然不多,但最初的测试运行良好。

film=/home/wlgfx/longfilm.mkv
output=/home/wlgfx/longfilm.mp4

(ffmpeg -i $film -y -vcodec copy -acodec copy $output) & pid=$!
#for i in 'seq 1 10' # 10 seconds
#do
#    sleep 1
    if wait $pid; then echo "$pid success $?"
    else echo "$pid fail $?"
    fi
#done
Run Code Online (Sandbox Code Playgroud)

退出状态为$?

我还注意到 ffmpeg 只需大约 5 秒即可将 2Gb 文件转换到另一个容器中。我将进行更新,以便进行转码,并对脚本进行进一步更改以反映它们,以便它将在 x 秒后终止该进程。

目前,我正在看这里:https ://stackoverflow.com/a/1570351/2979092

EDIT4:通过运行单独的超时进程,这次,如果您的进程在超时内正确退出,则将显示成功退出代码。否则将终止挂起过程。

film=/home/wlgfx/longfilm.mkv
output=/home/wlgfx/longfilm.mp4

while : ; do

    #(ffmpeg -i $film -y -vcodec mpeg2video -acodec copy $output) & pid=$!
    (ffmpeg -i $film -y -vcodec copy -acodec copy $output) & pid=$!

    (sleep 25 ; echo 'timeout'; kill $pid) & killpid=$!

    wait $pid # will get status if completed successfully
    status=$?

    (kill -0 $killpid && kill $killpid) || true

    [[ $status == 0 ]] || break

done
Run Code Online (Sandbox Code Playgroud)