在 Bash 中,这将为慢命令设置 10 秒的时间限制
timeout 10 slowcommand
Run Code Online (Sandbox Code Playgroud)
我想知道如何获得相同的行为,如果我必须调用sudo才能运行slowcommand,即:
timeout 10 sudo slowcommand
Run Code Online (Sandbox Code Playgroud)
这将限制sudo,而不是slowcommand ......在使用 sudo 时有没有一种优雅的方法来做到这一点?
编辑:假设不允许使用 sudo 运行超时。
timeout不是bashshell 或任何与此相关的shell的内置/函数(除非您想考虑 busybox sh,其中 busybox 命令可以被视为 shell 的内置命令)。
timeout是一个非标准的独立实用程序,其中存在几个通常不兼容的实现(也存在timelimit具有相同功能的实用程序)。
在:
timeout 10 sudo slowcommand
Run Code Online (Sandbox Code Playgroud)
该timeout实用程序的 GNU 实现的当前版本(来自 GNU coreutils,再次与 GNU shell 不同bash),运行sudo slowcommand并将 SIGTERM 命令发送到它自己的进程组,如果sudo在 10 秒内未完成,。
然而,正在运行的进程sudo已经改变了用户 id,并且sudo产生运行的进程slowcommand也将使用不同的 uid 运行,因此即使两个进程将与正在运行的进程在同一个进程组中timeout,timeout将不会有发送信号到正确的他们。
有可能的方法来解决这个问题。您可以安排内核发送一些信号,而不是像运行timeout. 例如,你可以让它发送:
SIGPIPE 如果slowcommand写入封闭管道:
sudo slowcommand | timeout 10 cat
Run Code Online (Sandbox Code Playgroud)
会导致 SIGPIPE 被发送到 slowcommand如果它在 10 秒后向 stdout 写入一些内容,。
(顺便说一句,这里,cat,sudo和slowcommand都将在同一个进程组中运行,因此与 相同timeout 10 sudo slowcommand | cat)。
SIGXCPU 如果slowcommand使用超过其分配的 CPU 时间限制:
(ulimit -t 10; exec sudo slowcommand)
Run Code Online (Sandbox Code Playgroud)
slowcommand如果它使用 10 秒的 CPU 时间会导致被杀死。
SIGHUP 如果终端挂断,并且sudo不是会话领导者:
timeout 10 script -qfc 'sudo slowcommand; exit' /dev/null
Run Code Online (Sandbox Code Playgroud)
(这里假设util-linux脚本)
信号/信号退出。您还可以使用expect/ zpty/ script/ 之类的东西screen来模拟终端并^C在 10 秒后发送一个字符,以便将 SIGINT 发送到该终端的前台进程组。