![使用 sh -c 运行的脚本未收到信号](https://linux22.com/image/111621/%E4%BD%BF%E7%94%A8%20sh%20-c%20%E8%BF%90%E8%A1%8C%E7%9A%84%E8%84%9A%E6%9C%AC%E6%9C%AA%E6%94%B6%E5%88%B0%E4%BF%A1%E5%8F%B7.png)
我有一个脚本,在运行耗时的命令之前会休眠 3 分钟。我希望脚本退出,如果它SIGINT
仅在休眠时接收,而不是在执行长时间运行的命令时接收。这是为了确保在给定的时刻只有一个耗时命令的实例正在运行。
这是myscript.sh
:
#!/bin/bash
trap 'exit' INT
sleep 180 &
wait
trap '' INT
# Long running command
/etc/init.d/myd sync
我的运行方式如下:
kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &
现在,即使在后续运行中,它也能按预期工作。 IE
如果脚本未运行,它将运行该脚本。
SIGINT
如果脚本正在运行但尚未执行长时间运行的命令,则停止脚本 (send ),然后重新启动它。如果脚本正在运行并执行长时间运行的命令,则不执行任何操作。
然而,当我使用以下命令运行同一个班轮时sh -c
:
sh -c 'kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &'
如果脚本之前没有运行,它会启动该脚本,但它似乎无法停止该脚本。
我不明白为什么这不起作用。
答案1
所以我不得不稍微修改你的命令路径,但我相信这符合你的要求。但首先,我需要对您的脚本进行修改:
#!/bin/bash
# Make sure we know when the trap fires.
trap 'printf "quiting with return code %d\n" "$?"; exit' INT
sleep 180 &
wait
trap '' INT
# Long running command
/usr/bin/sleep 86400
然后,我可以通过更改第二个命令来完成您想要的操作,如下所示:
sh -c 'set -x; (exec kill --verbose -INT $(pgrep myscript.sh) 2>/dev/null); ! pgrep -x "myscript.sh" > /dev/null && /tmp/myscript.sh &'
一旦您确认以这种方式运行可以按预期工作,您可以从脚本中的第一个陷阱中删除 printf 语句并运行如下命令:
sh -c '(exec kill -INT $(pgrep myscript.sh) 2>/dev/null); ! pgrep -x "myscript.sh" > /dev/null && /tmp/myscript.sh &'
如果上面命令中第一条语句没有括号,这会使其在子 shell 中运行,则该sh
进程将被替换为该kill
进程,并且第二条语句将不会运行。