我有一个bash脚本,在发出守护进程信号之前等待3分钟.在这3分钟内,如果收到它,我需要它退出SIGINT.
我当前的脚本在从bash运行时工作,但是,当我使用该system()调用从另一个(C)程序中运行它exit时,它在发送时不会SIGINT.
这是我当前的脚本:
#!/bin/bash
trap 'exit' INT
sleep 180 &
wait
trap '' INT
/etc/init.d/myd sync
Run Code Online (Sandbox Code Playgroud)
这是我运行它的方式:
kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &
Run Code Online (Sandbox Code Playgroud)
使用system()呼叫运行时,同一个班轮不起作用.
PS:基本上,/etc/init.d/myd sync如果在3分钟内多次调用它,我只在最后一次调用它之后运行该命令.
要求的C代码:
system("kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x \"myscript.sh\" > /dev/null && /opt/my/scripts/myscript.sh &");
Run Code Online (Sandbox Code Playgroud)
C程序非常庞大(跨越数十个文件),所以我只是在这里粘贴特定的调用.该程序应该作为守护进程运行,但即使我不将其作为守护进程运行(使用命令行开关),我也会遇到此问题.
我可以使用以下简单的C代码重现这一点:
#include <stdlib.h>
int main(int argc, char *argv[]) {
system("kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x \"myscript.sh\" > /dev/null && /opt/my/scripts/myscript.sh &");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
bash,而不是myscript.shsh调用system()来匹配自身经过对各种操作系统的一些讨论和测试,一旦消除了微妙之处,这实际上可以归结为:
ps将显示以下内容:46694 s001 S+ 0:00.01 /bin/bash /opt/my/scripts/myscript.shRun Code Online (Sandbox Code Playgroud)
system()从调用(通过sh)启动脚本时,ps将显示以下内容:46796 s002 S 0:00.00 /bin/bash /opt/my/scripts/myscript.shRun Code Online (Sandbox Code Playgroud)
从ps手册中:
state 第一个字符表示进程的运行状态: S 标记睡眠时间少于 20 秒的进程
这些后面的附加字符(如果有), 指示附加状态信息:
+ 该进程位于其控制终端的前台进程组中。
所以没有+ 的进程不会使用 SIGINT。
事实证明我们可以捕获SIGUSR1并将其发送kill -USR1
cmon.c
#include
int main(int argc, char *argv[]) {
system("mypid=`cat /opt/my/scripts/myscript.pid` ; ps -p $mypid > /dev/null && kill -USR1 $mypid 2>/dev/null ; mypid=`cat /opt/my/scripts/myscript.pid` ; ps -p $mypid > /dev/null || /opt/my/scripts/myscript.sh &");
return 0;
}
Run Code Online (Sandbox Code Playgroud)/opt/my/scripts/myscript.sh
#!/bin/bash
#process for this instance of bash
bashpid="$$"
#ensure single instance
mypid="$(cat "$(dirname "$0")/myscript.pid" 2>/dev/null)"
ps -p $mypid &> /dev/null && (echo "already running, now going to exit this instance" ; echo "seems we never see this message, that's good, means the system() call is only spawning a new instance if there's no process match." ; kill -9 "$bashpid")
#set pidfile for this instance
echo "$bashpid" > "$(dirname "$0")/myscript.pid"
trap 'echo "BYE" ; exit' SIGUSR1
sleep 5 & # 30 seconds for testing
wait
trap '' SIGUSR1
echo "Sitting here in limbo land" & while true ; do sleep 5 ; doneRun Code Online (Sandbox Code Playgroud)./cmon循环二进制文件并检查每次是否得到不同的进程(在超时窗口内)的简单行:
unset i ; until [[ i -eq 5 ]] ; do ./cmon ; ps ax | grep bash.*myscript.sh | grep -v grep | awk -F ' ' '{print $1 " " $6}' ; sleep 1 ; (( i ++ )) ; done
Run Code Online (Sandbox Code Playgroud)
一旦超时到期,可以运行同一行,以检查所有进程号是否相同
可以在此处找到可粘贴的完整单元测试构建和测试序列: ybin 链接
它的演示在这里运行:
有关过程的注意事项:
OP 确认最终工作后进行更新