如果其运行时间超过某个预定值,则自动终止进程

use*_*ser 6 bash timeout

我想从一个 shell 脚本启动一个进程,允许它与用户交互(所以我不能只是后台它,获取 PID,启动,sleep然后是健全性检查和kill),但如果它在一段时间后仍在运行(比如说,两分钟),然后我才想杀死它。

目的是简单地为没有内置该功能的程序实现挂钟运行时超时。

有没有办法做到这一点,最好是从 bash shell 脚本?

Ign*_*ams 7

BASH 常见问题条目 #68:“如何运行命令,并让它在 N 秒后中止(超时)?”

首先检查是否可以直接告诉您正在运行的命令超时。此处描述的方法是“hacky”变通方法,可强制命令在经过特定时间后终止。正确配置您的命令总是比下面的替代方案更可取。

如果该命令不支持在指定时间后停止,那么最好的替代方法是一些称为 timeout 和 doalarm 的外部命令。一些 Linux 发行版以包的形式提供超时的 tct 版本。还有一个 GNU 版本的 timeout,包含在最近的 coreutils 版本中。

注意:默认情况下,超时的某些实现会发出 SIGKILL (kill -9),这与拔掉电源线大致相同(使程序没有机会提交其工作,通常会导致其数据损坏)。您应该使用允许程序自行关闭的信号 (SIGTERM)。有关 SIGKILL 的更多信息,请参阅 ProcessManagement。

doalarm 和 timeout 的主要区别在于 doalarm 在设置闹钟后“执行”程序,这使得它在 WrapperScript 中非常棒;而 timeout 作为子进程启动程序然后挂起(两个进程同时存在),这使它有机会在必要时发送多个信号。

如果您没有或不想要上述程序之一,您可以使用 perl one-liner 设置一个 ALRM,然后在时间限制内执行您想要运行的程序。无论如何,您必须了解您的程序对 SIGALRM 的作用;具有定期更新的程序通常为此目的使用 ALRM 并在收到该信号时进行更新而不是死亡。

doalarm() { perl -e 'alarm shift; exec @ARGV' "$@"; }

doalarm ${NUMBER_OF_SECONDS_BEFORE_ALRMING} program arg arg ...
Run Code Online (Sandbox Code Playgroud)

如果您不能或不会使用这些程序之一(30 年前这些程序确实应该包含在基本的核心 Unix 实用程序中!),那么您能做的最好的事情就是做一个丑陋的 hack,例如:

 command & pid=$!
 { sleep 10; kill $pid; } &
Run Code Online (Sandbox Code Playgroud)

您很快就会发现,如果它在交互式 shell 中运行,无论超时条件是否启动,都会产生相当多的混乱。清理它不值得我花时间。此外,它不能与任何需要前台终端的命令一起使用,例如 top。

可以做类似的事情,但要在前台保持命令:

 bash -c '(sleep 10; kill $$) & exec command'
Run Code Online (Sandbox Code Playgroud)

kill $$会杀死外壳,除了 exec 导致命令接管外壳的 PID。有必要使用 bash -c 以便不替换调用 shell;在 bash 4 中,可以使用子 shell 代替:

 ( cmdpid=$BASHPID; (sleep 10; kill $cmdpid) & exec command )
Run Code Online (Sandbox Code Playgroud)

shell 脚本“超时”(不要与命令“超时”混淆)使用上述第二种方法。它具有立即工作的优点(无需编译程序),但存在问题,例如程序读取标准输入。

只需使用超时或 doalarm 代替。真的。


Gil*_*il' 7

在一个足够新的 Linux 系统上(更准确地说,使用 GNU coreutils ?8.5),它就像

timeout 2m myprogram
Run Code Online (Sandbox Code Playgroud)

仅使用 POSIX shell 功能,您可以接近,但如果发生超时,则会出现一个小的竞争条件(理论上,第二个后台进程的 PID 可以在kill $s执行前重新使用)。

myprogram <>/dev/tty & p=$!;
{ sleep 120; kill $p; } & s=$!;
wait $p; kill $s
Run Code Online (Sandbox Code Playgroud)

即使您需要程序的输出,也有一种很好的方法,没有竞争条件。这是一个使用向进程组发送信号的能力的绝妙技巧。这要归功于 Stéphane Gimenez

sh -ic '{ myprogram <>/dev/tty; kill 0; } |
        { sleep 120; kill 0; }'
Run Code Online (Sandbox Code Playgroud)