如何对需要 sudo 的命令使用 bash 超时功能?

su_*_*_li 1 bash timeout

在 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 运行超时

Sté*_*las 6

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 运行,因此即使两个进程将与正在运行的进程在同一个进程组中timeouttimeout将不会有发送信号到正确的他们。

有可能的方法来解决这个问题。您可以安排内核发送一些信号,而不是像运行timeout. 例如,你可以让它发送:

  • SIGPIPE 如果slowcommand写入封闭管道:

    sudo slowcommand | timeout 10 cat
    
    Run Code Online (Sandbox Code Playgroud)

    会导致 SIGPIPE 被发送到 slowcommand如果它在 10 秒后向 stdout 写入一些内容,。

    (顺便说一句,这里,catsudoslowcommand都将在同一个进程组中运行,因此与 相同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 发送到该终端的前台进程组。