如何使用运行Bash的前台子进程可靠地使用陷阱 [英] How to use trap reliably using Bash running foreground child processes

查看:52
本文介绍了如何使用运行Bash的前台子进程可靠地使用陷阱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Bash脚本,它在前台运行一个长时间运行的进程.当它收到SIGQUIT信号时,应执行各种清除操作,例如杀死自身及其所有子进程(通过杀死进程组等).下面显示了一个应该捕获信号的最小脚本(称为 test_trap.sh ):

I have a Bash script that runs a long running process in the foreground. When it receives a SIGQUIT signal, it should perform various cleanup operations such as killing itself and all of its child processes (via kill of process group etc.). A minimal script, that should catch the signal, is shown below (called test_trap.sh):

#!/bin/bash

trap 'echo "TRAP CAUGHT"; exit 1' QUIT  # other required signals are omitted for brevity

echo starting sleep
sleep 11666
echo ending sleep

echo done

我想将SIGHUP信号发送到 test_trap.sh 脚本的过程.但是,将SIGHUP发送到 test_trap.sh 不会触发陷阱表达式,只有当我将信号发送给子 sleep 11666 进程时,陷阱才会触发.下面是一个bash会话,演示了这一点:

I would like to send the SIGHUP signal to the process of the test_trap.sh script. However, sending a SIGHUP to the test_trap.sh does not trigger the trap expression, but only when I send the signal to the child sleep 11666 process does the trap fire. Below is a bash session demonstrating this:

bash-4.1$ test_trap.sh &
[1] 19633
bash-4.1$ starting sleep

bash-4.1$ kill -s SIGQUIT 19633
bash-4.1$ jobs
[1]+  Running                 test_trap.sh &
bash-4.1$ ps -ef --forest --cols=10000 | grep '11666\|test_trap.sh' | grep -v grep
theuser   19633 12227  0 07:40 pts/4    00:00:00              \_ /bin/bash ./test_trap.sh
theuser   19634 19633  0 07:40 pts/4    00:00:00              |   \_ sleep 11666
bash-4.1$ kill -s SIGQUIT 19634
bash-4.1$ Quit (core dumped)
TRAP CAUGHT

[1]+  Exit 1                  test_trap.sh
bash-4.1$ ps -ef --forest --cols=10000 | grep '11666\|test_trap.sh' | grep -v grep
bash-4.1$ 

请注意,"sleep 11666"只是一个代表性的过程.该过程实际上可以是一个交互式子shell(例如, bash -i ).

Note that the "sleep 11666" is just a representative process. That process can actually be an interactive subshell (e.g., bash -i).

为什么父 test_trap.sh 进程没有捕获到SIGHUP信号?为什么只有通知 sleep 11666 的进程时陷阱才会触发?

Why doesn't the parent test_trap.sh process catch the SIGHUP signal? Why would the trap fire only when the process for sleep 11666 was signaled?

我不想使用不可捕获的SIGKILL,因为我确实需要在trap表达式中进行各种清理操作.

I do not want to use uncatchable SIGKILL as I do need to do an assortment of cleanup operations in the trap expression.

该脚本旨在在包含Bash的任何Linux发行版的任何较新版本上运行(例如,非Cygwin).

This script is intended run on any fairly recent version of any Linux distribution containing Bash (e.g., not Cygwin).

参考文献:

  1. 使用SIGKILL杀死父进程以及子进程
  2. 杀死bash和子进程

推荐答案

bash 必须等待 sleep 完成,然后才能执行处理程序.一个好的解决方法是在后台运行 sleep ,然后立即等待.虽然 sleep 是不间断的,但 wait 不是.

bash must wait for sleep to complete before it can execute the handler. A good workaround is to run sleep in the background, then immediately wait for it. While sleep is uninterruptible, wait is not.

trap 'kill $sleep_pid; echo "TRAP CAUGHT"; exit 1' QUIT

echo starting sleep
sleep 11666 &
sleep_pid=$!
wait
echo ending sleep

echo done

记录 sleep_pid 并用于从处理程序中杀死 sleep 是可选的.

The recording of sleep_pid and using it to kill sleep from the handler are optional.

这篇关于如何使用运行Bash的前台子进程可靠地使用陷阱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆