Linux 为什么可以';在脚本中启用作业控制时,我是否捕获进程信号?

Linux 为什么可以';在脚本中启用作业控制时,我是否捕获进程信号?,linux,bash,shell,Linux,Bash,Shell,当我在shell脚本中启用作业控制时(使用set-m),我不再能够捕获进程信号。请看下面的代码: #!/bin/bash set -m for i in `seq 15`; do trap 'echo " Signal $i catched"' $i done while true; do echo " Waiting for a process signal" sleep 999 done 当我运行上述代码并按下例如Ctrl+C时,不会发生任何事情: Waiti

当我在shell脚本中启用作业控制时(使用
set-m
),我不再能够捕获进程信号。请看下面的代码:

#!/bin/bash

set -m

for i in `seq 15`; do
    trap 'echo " Signal $i catched"' $i
done

while true; do
    echo " Waiting for a process signal"
    sleep 999
done
当我运行上述代码并按下例如Ctrl+C时,不会发生任何事情:

Waiting for a process signal
^CWaiting for a process signal
但是,当我运行相同的代码删除
set-m
时,我确实得到了一个答案:

Waiting for a process signal
^C Signal 15 catched
我的问题是:

  • 为什么它不起作用
  • 当作业控制启用时,是否可以捕获过程信号

  • 注意:并非所有进程都会发生这种情况,如果我使用
    read
    而不是
    sleep
    ,它确实有效。

    解决方案是将sleep放在后台,并使用bash内置的
    wait
    在睡眠完成时等待。因此,请尝试以下方法:

    #!/bin/bash
    
    set -m
    
    for i in `seq 15`; do
        trap 'echo " Signal $i catched"' $i
    done
    
    while true; do
        echo " Waiting for a process signal"
        sleep 999 & wait $!
    done
    
    样本运行:

    $ bash script
     Waiting for a process signal
    ^C Signal 15 catched
     Waiting for a process signal
    ^C Signal 15 catched
     Waiting for a process signal
    

    有关更多详细信息,请参阅。

    为什么首先要在脚本中启用作业控制?作业控制通过在不同于shell的进程组中运行外部程序来工作。键盘信号只发送到前台进程组,当程序运行时,shell不在前台组中。@Barmar在某些情况下,作业控制在脚本中很有用。例如,当我在后台启动一个新流程时,如果我将来需要杀死整个流程组,我将无法这样做。因为,当未启用作业控制时,不会创建新的进程组,所有创建的进程都将属于当前组。使此解决方案更好的是,它不仅可以完美地工作,而且可以与任何调用的程序一起工作。因为,无论调用什么程序,它都将放在后台,
    wait
    将在前台捕获所有信号。