我正在尝试理解这个脚本:
#!/usr/bin/env sh
trap "pkill -f sleep" term
sleep 1000
运行脚本后,我想通过发送SIGTERM
来停止它:
# run script in the background
$ ./signals.sh &
[1] 5389
# check if script is running
$ ps aux | grep 'signals.sh|sleep' | grep -v grep
sergioro 5389 0.0 0.0 216520 3112 pts/0 S 09:07 0:00 sh ./signals.sh
sergioro 5390 0.0 0.0 214984 708 pts/0 S 09:07 0:00 sleep 1000
# send SIGTERM to script
$ pkill -fe signals.sh
sh killed (pid 5389)
# why hasn't the script stopped after receiving SIGTERM?
$ ps aux | grep 'signals.sh|sleep' | grep -v grep
sergioro 5389 0.0 0.0 216520 3112 pts/0 S 09:07 0:00 sh ./signals.sh
sergioro 5390 0.0 0.0 214984 708 pts/0 S 09:07 0:00 sleep 1000
# send SIGTERM to `sleep` command
$ pkill -fe sleep
sleep killed (pid 5390)
Terminated
# script has stopped
$ ps aux | grep 'signals.sh|sleep' | grep -v grep
我的问题是如何通过将SIGTERM
发送到脚本本身而不是sleep
命令来停止脚本?为什么脚本中的trap
不终止睡眠命令?
外壳只有在sleep
完成后才能处理trap
。
这可以达到您的预期:
#!/usr/bin/env sh
trap "pkill -f sleep" term
sleep 1000 & wait
请参阅手册页的 SIGNALS 部分,尤其是最后一段:
如果 bash 正在等待命令完成并收到信号 设置了陷阱,则在命令完成之前不会执行陷阱。 当 bash 正在等待异步命令时,通过 内置等待,接收陷阱的信号 set 将导致内置的等待立即返回,退出状态大于 128,之后立即执行陷阱。