POSIX是否等同于GNU超时?


14

timeout对于某些脚本情况,GNU coreutils 命令非常方便,如果可以快速运行,则允许使用命令的输出;如果花费太长时间,可以跳过该命令的输出。

如何近似timeout仅使用POSIX指定的实用程序的基本行为?


(我想它可能涉及的组合waitsleepkill和谁知道什么,但也许我失去了一个更简单的方法。)


3
请参阅在shell脚本中超时,但是我不认为这是重复的,因为我要求可移植到POSIX之前的系统,并且我要求保留stdin和stdout,而某些涉及后台进程的解决方案则对此予以排除。
吉尔(Gilles)“所以,别再邪恶了”

command & pid=$! ; sleep 5 && kill $pid
潘迪

1
@Pandya不会引入轻微的竞争状态,如果运行command迅速pid,在kill命令运行之前是否有被另一个进程重新使用的可能性很小?我不想在生产代码
通配符

您能否进一步说明您要解决的潜在问题?为什么不只是编译timeout程序并使用它呢?
James Youngman

2
@JamesYoungman,我想您对编写可移植性脚本不是很熟悉。要求一种符合POSIX(或POSIX指定)的方式来做某事意味着它是可移植的。显然,将源代码编译成二进制文件是不可移植的,并且,根据公司的安全策略,您可能根本没有生产服务器上安装编译器。
通配符

Answers:


2

我的方法是这样的:

  • 执行命令作为后台进程1

  • 执行“看门狗计时器”作为后台进程2

  • 设置处理程序以在父外壳中捕获终止信号

  • 等待两个过程完成。首先终止的过程将终止信号发送给父级。

  • 父级的陷阱处理程序通过作业控制杀死了两个后台进程(其中一个已经按照定义终止了,但是这种杀死将是无害的无操作操作,因为我们没有使用PID,请参见下文)

我试图通过使用shell的作业控制ID(在该shell实例中是明确的)来标识要杀死的后台进程,而不是系统PID,以规避注释中提到的可能的竞争状况。

#!/bin/sh

TIMEOUT=$1
COMMAND='sleep 5'

function cleanup {
    echo "SIGTERM trap"
    kill %1 %2
}

trap cleanup SIGTERM

($COMMAND; echo "Command completed"; kill $$) &
(sleep $TIMEOUT; echo "Timeout expired"; kill $$) &

wait
echo "End of execution"

结果TIMEOUT=10(命令在监视程序之前终止):

$ ./timeout.sh 10
Command completed
SIGTERM trap
End of execution

结果TIMEOUT=1(看门狗在命令之前终止):

$ ./timeout.sh 1
Timeout expired
SIGTERM trap
End of execution

结果TIMEOUT=5(看门狗和命令“几乎同时终止”):

./tst.sh 5
Timeout expired
Command completed
SIGTERM trap
End of execution

这不符合POSIX,因为(a)函数定义应该是cleanup() { ...; }(b)作业控制是POSIX未指定的bash功能(尽管ksh和其他人也有此功能)。不错的脚本,但是!
通配符

你也可以做更好的timeout="$1"; shift(exec "$@"; echo "Command completed"; kill $$),而不是重新wordsplitting参数列表。
通配符
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.