使用 sh -c 运行的脚本未收到信号

使用 sh -c 运行的脚本未收到信号

我有一个脚本,在运行耗时的命令之前会休眠 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

  1. 如果脚本未运行,它将运行该脚本。

  2. SIGINT如果脚本正在运行但尚未执行长时间运行的命令,则停止脚本 (send ),然后重新启动它。

  3. 如果脚本正在运行并执行长时间运行的命令,则不执行任何操作。

然而,当我使用以下命令运行同一个班轮时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进程,并且第二条语句将不会运行。

相关内容