这可能听起来微不足道,但我很确定这个问题没有被问过,或者至少我找不到它.
我正在寻找一种方法来构建一个无限等待(不一定是一个循环)与shell脚本,以便它永远等待,并可以被杀死(或技术上,接收一个SIGTERM).以下是已知的可能的构造和反对它们的参数:
while true; do sleep 1; done这几乎得到它,但由于sleep是一个外部命令,当我发送SIGTERM到正在运行的脚本时,它必须等待sleep先完成然后处理信号.换成sleep 1类似的东西sleep 10,滞后很明显.该解决方案每1秒唤醒一次CPU,这并不理想.while true; do read; donestdintty 时这是完美的.read是一个内置的shell,SIGTERM立即到达脚本.但是,当stdin是/dev/null时,脚本吃掉的无奈运行所有的CPU read永远都在/dev/null.因此,需要一个永远等待的shell内置构造.通过略读man dash我没有找到这样的一个-唯一的阻挡内建有read和wait,和我没有想法,我怎么可以构建采用理想的一个wait.
答案应该适用于POSIX shell(有效dash),或者不太适合Bash.
补充说明.
第一个例子不能完美运行的情况比我想象的要复杂得多.使用以下shell脚本:
#!/bin/sh
echo $$
while true; do
sleep 100
done
Run Code Online (Sandbox Code Playgroud)
如果你在另一个tty杀死它,它会立即终止.当你试图捕捉时,有趣的事情就开始了.使用此脚本:
#!/bin/sh
at_term() {
echo 'Terminated.'
exit 0
}
trap at_term TERM
echo $$
while true; do
sleep 20
done
Run Code Online (Sandbox Code Playgroud)
发生的情况在示例1中有详细描述.这种情况发生在bash,dash和zsh中.在这种情况下,我正在寻求一种"完美"的无限外观构造.
tec*_*rus 16
您可以使用命名管道进行阅读:
mkfifo /tmp/mypipe
#or mknode /tmp/mypipe p
Run Code Online (Sandbox Code Playgroud)
如果您以后想要向管道发送不同的任意"信号",则可以将读取与case语句结合使用以采取适当的操作(即使是有用的操作)
while read SIGNAL; do
case "$SIGNAL" in
*EXIT*)break;;
*)echo "signal $SIGNAL is unsupported" >/dev/stderr;;
esac
done < /tmp/mypipe
Run Code Online (Sandbox Code Playgroud)
yin*_*ted 10
如果您有GNU coreutils,它接受浮点秒,您可以尝试:
sleep inf
Run Code Online (Sandbox Code Playgroud)
这应该阻塞直到64位时间戳环绕.
小智 7
这是一个没有循环的解决方案:
#!/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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11939 次 |
| 最近记录: |