Bash 中的 timeout 命令
本文是使用 Bash 中 GNU 的 coreutils 包的 timeout 命令为特定程序设置超时的简单指南。
Bash 中的 timeout 命令
在许多情况下,例如从服务器获取数据或使用随机输入运行函数或程序,程序或函数可能会运行很长时间或无限期地运行。
在这种情况下,停止程序并防止它浪费更多的时间和资源是必不可少的。
这就是超时功能的用武之地。用户定义一个时间限制,然后允许程序运行直到成功完成,如果在用户定义的时间限制之前花费的时间太长,则程序将被终止。
大多数编程语言通常内置超时功能。 但是,对于 Bash,它不是内置的,而是名为 coreutils 的外部包的一部分。
这个包由 GNU 开发和维护,包含许多基本实用程序的实现。
只需在 LINUX 系统中运行命令 sudo apt-get install -y coreutils
即可安装 coreutils 包。
您必须先安装 Homebrew 才能在 macOS 系统上获取 coreutils。 要获取 Homebrew,请在命令终端中运行以下命令。
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
完成 Homebrew 安装后,运行以下命令。
brew install coreutils
如果你安装了 coreutils 包,你可以简单地使用超时功能,例如:
timeout 10 ping baidu.com
Bash 中的 ping 实用程序是内置的,并且会继续运行直到手动中断。 默认情况下,ping 每 1 秒发送一个包。
如上所示,超时命令在 10 秒后终止 ping,因为超时命令后的数字是时间限制。
因此,命令 timeout 10 cmd1 表示 cmd1 将运行直到成功完成或 10 秒,以较早者为准。 超时命令的时间单位是秒。
要使用以分钟、小时或天为单位的时间值,请分别添加 m、h 或 d。
例如,要设置 2 分钟的超时:
timeout 2m programToRun
需要注意的是,当进程超时时,超时的退出状态为124。 在下面的示例中,我们将使用它来检查进程是否超时。
timeout 1 ping 8.8.8.8 -w3
EXIT_STATUS=$?
if [ $EXIT_STATUS -eq 124 ]
then
echo 'Process timed out!'
else
echo 'Process did not timeout.'
fi
exit $EXIT_STATUS
在上述示例中,如果进程未在 1 秒内完成,则进程将超时。 -w3
扩展表示该地址将被 ping 三次。
因此,此过程将始终超时,并给出以下输出。
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=40.4 ms
Process timed out!
重要的是要注意任何内部超时也会导致相同的退出状态 (124)。 因此,此输出表明进程使用我们指定的超时超时或某些内部超时使其终止。
在 Bash 中使用超时和 SIGKILL 信号
通常,超时函数会在达到时间限制时发送 SIGTERM 信号以停止程序的执行。 问题是某些程序可能会忽略 SIGTERM 信号并继续运行。
这就是 SIGKILL 信号出现的地方; 它立即停止执行一个进程及其所有子进程,并且不能被阻止或忽略。 要使用 SIGKILL 超时,我们必须添加 -s 标志。
例如:
timeout -s SIGKILL 10 programToRun
当不直接从 shell 运行 timeout
时,就像从脚本运行它一样,将 --foreground 添加到 timeout
命令很重要。
可以使用超时命令的许多替代方法,所有这些都主要基于相同的逻辑,即在睡眠时使用一些终止信号,然后运行所需的命令或程序,一旦睡眠结束,这些命令或程序就会停止。
例子:
(sleep 2 && killall prog) & ./prog
如果 prog 还没有完成执行,上面的代码将在 2 秒后杀死 prog
的所有进程。 这样的解决方案可以工作,但不如 timeout 命令安全可靠,因此最好改用 timeout。
相关文章
在 Bash 中运行 find -exec 命令
发布时间:2024/03/14 浏览次数:127 分类:操作系统
-
本文将演示如何使用 find 命令的 -exec 参数来使用 find 命令定位文件中的任何文本。