如何通过脚本集合传播信号?

发布于 2024-08-26 17:04:33 字数 213 浏览 12 评论 0原文

我有一组由主要脚本控制的脚本。我想在主脚本中捕获信号 ctrl+c 并将其传播给其他脚本。其他脚本也应该捕获这个信号(来自主脚本)并进行一些清理...

我尝试向孩子们发送 kill -s SIGINT ,但他们似乎无法捕获信号(即使在子脚本上定义了陷阱'Cleanup'SIGINT)

任何线索如何实现这一点?

I have an collection of scripts which are controlled by a main one. I want to trap the signal ctrl+c in the main script and propagate it to the others. The other scripts should trap this signal as well ( from the main script ) and do some clean-up ...

I have tried to send kill -s SIGINT to the children, but they seem they are unable to catch the signal( even if trap 'Cleanup' SIGINT being defined on the children scripts )

Any clues how to realize this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

毁我热情 2024-09-02 17:04:33

以下示例演示了一个父脚本,该父脚本在启动两个执行自己操作的子脚本(也是 sleep 5)后执行某些操作(sleep 5)。当父进程退出(无论出于何种原因)时,它会向子进程发出终止信号(不要使用 SIGINT,终止由 SIGTERM 发出信号,也是默认的 kill信号)。然后,孩子们在收到 SIGTERM 后就开始做自己的事情。如果子级是自己的脚本,我建议您将 TERM 上的陷阱更改为 EXIT 上的陷阱,以便子级清除,无论其终止原因是什么是(只要它是可捕获的)。

请注意我使用了wait。 Bash 在收到信号时不会中断运行非内置命令。相反,它等待它们完成并在命令完成后处理信号。如果您使用 wait,bash 会立即停止等待并立即处理信号。

#!/usr/bin/env bash

trap 'echo parent shutting down; kill $(jobs -p)' EXIT

{ trap 'echo child 1 signaled' TERM; sleep 5 & wait; } &
{ trap 'echo child 2 signaled' TERM; sleep 5 & wait; } &

sleep 5

The following example demonstrates a parent script that does something (sleep 5) after it starts two children that do their own thing (also sleep 5). When the parent exits (for whatever reason) it signals the children to terminate (don't SIGINT, termination is signaled by SIGTERM, also the default kill signal). The children then do their thing on reception of SIGTERM. If the children are scripts of their own, I recommend you change the trap on TERM into a trap on EXIT so that the children clean up no matter what the cause of their termination be (so long as it's trappable).

Notice my use of wait. Bash does not interrupt running non-builtin commands when it receives a signal. Instead, it waits for them to complete and handles the signal after the command is done. If you use wait, bash stops waiting immediately and handles the signal right away.

#!/usr/bin/env bash

trap 'echo parent shutting down; kill $(jobs -p)' EXIT

{ trap 'echo child 1 signaled' TERM; sleep 5 & wait; } &
{ trap 'echo child 2 signaled' TERM; sleep 5 & wait; } &

sleep 5
桜花祭 2024-09-02 17:04:33

您是否尝试过:
1) 在每个脚本(主脚本/子脚本)中需要的地方设置陷阱
2)向master发送一个kill,其PID被否定,以杀死整个进程组,我的意思是

kill -15 -$PID

: grep -C1 负数

Have you tried to :
1) Setup your traps in every script (master / childs) where you need them
2) Send to the master a kill with it's PID negated, to kill the whole process group, I mean :

kill -15 -$PID

man kill | grep -C1 Negative

合久必婚 2024-09-02 17:04:33

主循环之前的主父脚本标头:::

#Catch control-c and clean up testd instances if necessary
cleanup () {
    clear
    echo "Caught Signal.  Shutting Down MAIN."
    if [ "$MAIN_on" -eq 1 ]
    then
    M_shutdown
    fi
    exit 1
  }

在脚本的主体中,当您生成子进程时,您将维护一个包含每个子进程的 proc id 的数组。要将 PID 加载到数组中,请将值设置为最后生成的进程,例如在每个子 shell 生成之后放置以下内容。

proc_id_array[1]=$!

M_shutdow 的内容类似于...

M_shutdown () {

    if [ "$MAIN_on" -eq 1 ]
    then
    echo "Stopping Main"
    echo "shutting down active subscripts"
    count_proc_id=1


while [ "$count_proc_id" -lt "$max_proc_id" ]
        do

            kill ${proc_id_array[$count_proc_id]} > /dev/null 2>&1
            DATE=$(date +%m%d%y-%k:%M)
            echo "$DATE: ${proc_name_array[$count_proc_id]} \(PID: ${proc_id_array[$count_proc_id]}\) stopped." >> $logfile             
            proc_id_array[$count_proc_id]="A"
            count_proc_id=`expr $count_proc_id + 1`
        done


        echo "MAIN stopped"
        MAIN_on=0

        sleep 5
        else
        echo "MAIN already stopped."
        sleep 1
        fi
    }

MAIN PARENT SCRIPT HEADER BEFORE THE MAIN LOOP:::

#Catch control-c and clean up testd instances if necessary
cleanup () {
    clear
    echo "Caught Signal.  Shutting Down MAIN."
    if [ "$MAIN_on" -eq 1 ]
    then
    M_shutdown
    fi
    exit 1
  }

In the main body of the script, as you spawn subprocesses you maintain an array with the proc ids of each. To load the PID into the array set the value to last spawned process e.g. put the following after each sub-shell spawn.

proc_id_array[1]=$!

Contents of the M_shutdow would be something like...

M_shutdown () {

    if [ "$MAIN_on" -eq 1 ]
    then
    echo "Stopping Main"
    echo "shutting down active subscripts"
    count_proc_id=1


while [ "$count_proc_id" -lt "$max_proc_id" ]
        do

            kill ${proc_id_array[$count_proc_id]} > /dev/null 2>&1
            DATE=$(date +%m%d%y-%k:%M)
            echo "$DATE: ${proc_name_array[$count_proc_id]} \(PID: ${proc_id_array[$count_proc_id]}\) stopped." >> $logfile             
            proc_id_array[$count_proc_id]="A"
            count_proc_id=`expr $count_proc_id + 1`
        done


        echo "MAIN stopped"
        MAIN_on=0

        sleep 5
        else
        echo "MAIN already stopped."
        sleep 1
        fi
    }
千紇 2024-09-02 17:04:33

我不确定“其他脚本应该从主脚本捕获此信号”是什么意思?子进程脚本如何使用主脚本中的代码来捕获信号?

我不想尝试为您编写太多代码,因为我也不确切知道“由主脚本控制的脚本”是什么意思,但大概您启动了一些子进程,然后有一个控制循环来检查另一个进程是否脚本已退出,并且可以获取其退出状态吗?如果是这样的话,对我来说最有意义的事情就是让每个脚本进行自己的捕获和清理。当主脚本捕获信号时,如果需要,它可以将信号传递给所有子脚本(通过kill -spid)。当子进程捕获信号时,它可以返回退出状态,表明它已被该信号终止。然后,main 可以适当地处理该退出状态 - 也许以与它本身收到该特定信号相同的方式进行处理。 (Shell 函数是你的朋友。)

I'm not sure what do you mean by "other scripts should trap this signal from the main script"? How can a subprocess script use code in the main script to trap a signal?

I don't want to try and write much code for you because I don't know exactly what you mean by "scripts controlled by a main one" either, but presumably you launch some subprocesses then have a control loop which checks if the other scripts have exited, and can grab their exit status? If that's the case, the thing that makes the most sense to me is for each script to do its own trapping and cleanup. When the main script traps a signal, it can if desired pass the signal along to all the children (via kill -s <signal> pid). When a child process traps a signal, it can return an exit status indicating that it was terminated by that signal. The main can then handle that exit status appropriately - perhaps in the same way as if it'd received that particular signal itself. (Shell functions are your friend.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文