在shell脚本中实现无限的等待

这可能听起来微不足道,但我很确定这个问题没有被问到,或者至less我找不到。

我正在寻找一种方法来构build一个无限的等待 (不一定是循环)与shell脚本,以便它永远等待,可以被杀害 (或技术上,接收SIGTERM )。 以下是已知的可能的结构和论点:

  1. while true; do sleep 1; done while true; do sleep 1; done这几乎得到它,但由于sleep是一个外部命令,当我发送一个SIGTERM到正在运行的脚本,它必须等待sleep完成,然后处理信号。 把sleep 1改变成像sleep 10 ,滞后将是显而易见的。 此外,解决scheme每1秒就会唤醒CPU,这并不理想。
  2. while true; do read; donestdin是tty时,这是完美的。 read是一个shell内部和SIGTERM即刻到达脚本。 但是,当stdin/dev/null ,脚本通过无可奈何地在/dev/null上永远运行read吞噬所有的CPU。

因此需要一个永远等待的shell内build构造 。 通过man dash略读,我没有find这样一个 – 唯一的阻止内置的readwait ,我不知道如何构build一个理想的使用wait

答案应该适用于POSIX shell(有效dash ),或者不太适合Bash。

补充笔记。

第一个例子并不完美的情况比我想象的要复杂得多。 使用下面的shell脚本:

 #!/bin/sh echo $$ while true; do sleep 100 done 

如果你在另一个tty中杀死它,它会立即终止。 有趣的事情开始时,你试图做陷阱。 用这个脚本:

 #!/bin/sh at_term() { echo 'Terminated.' exit 0 } trap at_term TERM echo $$ while true; do sleep 20 done 

会发生什么情况在示例1中有详细描述。这发生在bash,dash和zsh中。 在这种情况下,我正在寻求一个“完美的”无限的外观构造。

你可以使用一个命名管道来读取:

 mkfifo /tmp/mypipe #or mknode /tmp/mypipe p 

如果您稍后想要向管道发送不同的任意“信号”,则可以将读取与case语句结合使用以采取适当的操作(即使是有用的操作)

 while read SIGNAL; do case "$SIGNAL" in *EXIT*)break;; *)echo "signal $SIGNAL is unsupported" >/dev/stderr;; esac done < /tmp/mypipe 

如果你有GNU coreutils,它接受浮点秒,你可以尝试:

 sleep inf 

这应该阻塞,直到64位时间戳环绕。

这是一个没有循环的解决方案:

 #!/usr/local/bin/dash echo $$ # -$$: kill process group (parent and children) #trap 'trap - TERM; kill 0' TERM #trap 'trap - INT TERM; kill 0' INT TERM trap 'trap - TERM; kill -s TERM -- -$$' TERM tail -f /dev/null & wait exit 0 

你的第二个选项有什么问题,但强制它从stdin读取? (需要bash

 while true; do read done < /dev/stdin 

man bash

Bash处理几个文件名,特别是当它们用于重定向时,如下表所述:

  /dev/stdin File descriptor 0 is duplicated. 
 #!/bin/sh at_term() { echo 'Terminated.' exit 0 } trap at_term TERM echo $$ while true; do sleep 20 & wait $! done 

发送到进程的SIGTERM由内核传递给进程,无论它是否正在休眠。

尝试尝试,也许这样(bash例子)

 sleep 20 & kill $! && fg