使用system(3)运行bash脚本未收到信号

时间:2017-05-16 11:56:06

标签: bash

我有一个bash脚本,在发出守护进程信号之前会等待3分钟。 在这3分钟内,如果收到SIGINT,我需要退出。

我的当前脚本在从bash运行时有效,但是,当我使用system()调用从另一个(C)程序中运行它时,它在exit发送时SIGINT #!/bin/bash trap 'exit' INT sleep 180 & wait trap '' INT /etc/init.d/myd sync 1}}。

这是我目前的剧本:

kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &

以下是我如何运行它:

system()

使用/etc/init.d/myd sync调用运行时,同一个班轮不起作用。

PS: 基本上,如果在3分钟内多次调用system("kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x \"myscript.sh\" > /dev/null && /opt/my/scripts/myscript.sh &"); 命令,我只会在最后一次调用#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; } 之后运行function timeDiffInHours(milliseconds){ time_diff = (new Date).getTime() - milliseconds return parseInt((time_diff/(1000*60*60)) % 24) } // This is again sending current time and diff would be 0. timeDiffInHours((new Date).getTime()); 命令。

编辑1

要求的C代码:

{{1}}

C程序非常庞大(跨越数十个文件),所以我只是在这里粘贴特定的调用。该程序应该作为守护进程运行,但即使我不将其作为守护进程运行(使用命令行开关),我也会遇到此问题。

我可以使用以下简单的C代码重现这一点:

{{1}}

1 个答案:

答案 0 :(得分:1)

原因(更新):

  • 实际流程名称为bash,而非myscript.sh
  • pgrep可以通过sh调用
  • 中的system()进行匹配
  • SIGINT 当脚本在后台运行时,播放效果不佳。 (已使用SIGUSR1)

经过对各种操作系统的一些讨论和测试,一旦淘汰了细微之处,这真的归结为:

  1. 从tty启动脚本时,ps会显示:
  2. 46694 s001  S+     0:00.01 /bin/bash /opt/my/scripts/myscript.sh
    1. system()来电启动脚本(通过sh)时,ps会显示以下内容:
    2. 46796 s002  S      0:00.00 /bin/bash /opt/my/scripts/myscript.sh

      来自ps手册:

      •   
            
        • state   The first character indicates the run state of the process: 
          
              S   Marks a process that is sleeping for less than about 20 seconds
          Additional characters after these, if any, indicate additional state information:

          + The process is in the foreground process group of its control terminal.
        •   

      所以没有 + 的过程没有使用SIGINT。

      事实证明我们可以捕获 SIGUSR1 并发送 kill -USR1

      在Ubuntu 16.04上进行工作测试&amp; Mac OS X 10.12:

      <强> 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;
        }
        

      <强> /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 ; done

      测试

      简单地循环./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
      

      超时到期后可以运行相同的行,以检查所有进程号是否相同

      可在此处找到可粘贴的完整单元测试构建和测试序列: 的 ybin link

      它在这里运行的演示:

      enter image description here

      有关流程的说明

      • 仅为了便于测试而修改脚本(即10秒超时窗口)。
      • 冗余添加单实例检查(myscript.sh文件中的单实例触发器永远不会被触发......似乎永远不会被触发)

      当OP确认最终工作时更新以遵循