linux - Bash 脚本捕获信号但之后等待进程终止

标签 linux bash signals

目前我正在编写这样的 bash 脚本:

foo(){
  while true
  do
    sleep 10
  done
}

bar(){
  while true
  do
    sleep 20
  done
}

foo &
bar &

wait

(我知道这样的脚本没有意义,它只是关于结构)

现在我想用 trap -- <doSomething> RTMIN+1 添加信号处理.这首先起作用。当脚本收到 rtmin+1 信号时,它会执行 doSomething 但之后它存在(带有 163 退出代码,这是发送的信号的编号)。

这不是我想要的行为。我希望在收到信号后,脚本继续等待进程(在这种情况下是两个函数)终止(在这种情况下当然不会发生,但脚本应该等待)。

我尝试添加 ; wait接收信号时应该做的事情,但这无济于事(或者我做错了什么)。

有谁知道如何实现所需的行为?

提前致谢并致以最良好的祝愿。

编辑:也许一个更精确的例子有帮助:

clock(){
        local prefix=C
        local interval=1
        while true
        do
                printf "${prefix} $(date '+%d.%m %H:%M:%S')\n"
                sleep $interval
        done
}

volume(){
        prefix=V
                volstat="$(amixer get Master 2>/dev/null)"

                echo "$volstat" | grep "\[off\]" >/dev/null && icon="" #alternative: deaf:  mute: 

                vol=$(echo "$volstat" | grep -o "\[[0-9]\+%\]" | sed "s/[^0-9]*//g;1q")

                if [ -z "$icon" ] ; then
                if [ "$vol" -gt "50" ]; then
                        icon=""
                #elif [ "$vol" -gt "30" ]; then
                #       icon=""
                else
                        icon=""
                fi
                fi

                printf "${prefix}%s %3s%%\n" "$icon" "$vol"
}

clock &
volume &

trap -- "volume" RTMIN+2

wait

现在RTMIN+2信号应该重新运行 volume功能,但 clock过程不应中断。 (到目前为止,整个脚本(包括所有子进程)在接收到信号时终止)

最佳答案

当没有操作数调用时,wait退出 0 ;这意味着调用 shell 已知的所有进程 ID 都已终止,或者 大于 128 的值;这意味着接收到已设置陷阱的信号。所以,循环直到 wait退出 0足以让脚本在收到信号后保持事件状态。您还可以在循环内检查其退出状态是否小于 128,但我认为没有必要。

但是,如果您使用 pkill 发送这些信号,在后台启动的作业也将接收它们,因为子进程从其父进程继承进程名称而不是自定义信号处理程序,以及 pkill向名称匹配的所有进程发出信号。你也需要处理这种情况。

一个最小的工作示例是:

#! /bin/bash -
# ignore RTMIN+1 and RTMIN+2 temporarily
# to prevent pkill from killing jobs
trap '' RTMIN+1 RTMIN+2

# start jobs
sleep 20 && echo slept for 20 seconds &
sleep 30 && echo slept for 30 seconds &

# set traps
trap 'echo received rtmin+1' RTMIN+1
trap 'echo received rtmin+2' RTMIN+2

# wait for jobs to terminate
until wait; do
  echo still waiting
done

还值得注意的是,忽略 RTMIN+1RTMIN+2在开始作业之前可以防止从它们下降的 shell 捕获/重置这些信号。如果这是一个问题,您可以按照 F. Hauri 的建议在工作中设置一个空陷阱;或者你可以完全放弃忽略和使用 pkill-o选项将信号发送到最旧的匹配进程。

引用:
  • Shell Command Language § Signals and Error Handling
  • wait spec. § EXIT STATUS

  • 有关的:
  • Reliably kill sleep process after USR1 signal
  • 关于linux - Bash 脚本捕获信号但之后等待进程终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61512635/

    相关文章:

    linux - 从函数调用时无法读取输入

    c - 在多线程环境中捕获信号

    c - 死后用子进程替换父进程

    unix - 如何在 Go 中以跨平台的方式按名称列出可用的操作系统信号?

    linux - 更改KNOPPIX 7.0.4启动

    linux - 如何检查设备的文件系统类型?

    linux - 在 shell 中解析 ps 和 grep 输出

    linux - awk中的键值对

    linux - 使用 Bash 找出一个目录中是否有任何文件?

    linux - Bash 脚本作为屏幕保护程序