shell向子进程发送信号

Posted petewell

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell向子进程发送信号相关的知识,希望对你有一定的参考价值。

处理包含子进程的脚本,假设您希望终止任意子进程,那么还需要停止这些脚本。trap 命令完成此操作。

子进程

& 运行的子进程,最为后台程序运行,父进程与子进程之间为异步

已直接方式运行子进程,此时子进程在前台运行,父进程与子进程之间为同步

sleep 10   #等待10秒,再继续下一操作
sleep 10 & #当前shell不等待,后台子shell等待

trap

Unix system by design doesn’t allow any script/program to trap SIGKILL due to security reasons.

Setting a trap for SIGKILL or SIGSTOP produces undefined results.

trap 捕捉到信号之后三种处理方式

  1. 执行一段代码来处理信号 trap "commands" signal-list or trap 'commands' signal-list
  2. 接受信号的默认操作,即恢复信号默认操作 trap signal-list
  3. 忽视信号 trap "" signal-list

注意事项:

  1. SIGKILL SIGSTOP SIGSEGV SIGCONT不设置捕捉
  2. 在捕捉到signal-list中指定的信号并执行完相应的命令之后, 如果这些命令没有将shell程序终止的话,shell程序将继续执行收到信号时所执行的命令后面的命令,这样将很容易导致shell程序无法终止。
  3. 在trap语句中,单引号和双引号是不同的,当shell程序第一次碰到trap语句时,将把commands中的命令扫描一遍。此时若commands是用单引号括起来的话,那么shell不会对commands中的变量和命令进行替换

Example

全部使用同步方式

#!/bin/bash
# trapchild

trap 'echo "[TRAP]I am going down, so killing off my processes.."; ps -a | grep sleep | xargs kill -9; wait; exit' SIGHUP SIGINT SIGQUIT SIGTERM SIGKILL

./a.sh
err=$?
if [ $err != 0 ]; then
    echo 3 $err
    exit 1
fi

echo "[TRAP]my process pid is: $$"
echo "[TRAP]my child pid list is: $pid"

wait
#!/bin/bash
# trapchild

trap 'echo "[a]ash I am going down, so killing off my processes.."; ps -a | grep sleep | xargs kill -9; wait; exit' SIGHUP SIGINT SIGQUIT SIGTERM SIGKILL

sleep 120
echo 1 $?
if [ $? != 0 ]; then
    echo 2 $?
    exit 1
fi

pid="$!"

echo "[a]my process pid is: $$"
echo "[a]my child pid list is: $pid"

wait

执行trap.sh 之后会有三个进程

$ ps -a
  PID TTY          TIME CMD
  750 pts/5    00:00:00 trap.sh
  751 pts/5    00:00:00 a.sh
  752 pts/5    00:00:00 sleep

此时执行 kill -15 750kill-15 751 不会起作用,只有执行 kill -15 752 才会起作用,但是 trap 不会触发

使用异步方式

#!/bin/bash
# trapchild

trap 'echo "[TRAP]I am going down, so killing off my processes.."; ps -a | grep sleep | xargs kill -9; wait; exit' SIGHUP SIGINT SIGQUIT SIGTERM SIGKILL

./a.sh &
err=$?
if [ $err != 0 ]; then
    echo 3 $err
    exit 1
fi

echo "[TRAP]my process pid is: $$"
echo "[TRAP]my child pid list is: $pid"

wait
#!/bin/bash
# trapchild

trap 'echo "[a]ash I am going down, so killing off my processes.."; ps -a | grep sleep | xargs kill -9; wait; exit' SIGHUP SIGINT SIGQUIT SIGTERM SIGKILL

sleep 120 &
echo 1 $?
if [ $? != 0 ]; then
    echo 2 $?
    exit 1
fi

pid="$!"

echo "[a]my process pid is: $$"
echo "[a]my child pid list is: $pid"

wait

执行trap.sh 之后会有三个进程

$ ps -a
  PID TTY          TIME CMD
  750 pts/5    00:00:00 trap.sh
  751 pts/5    00:00:00 a.sh
  752 pts/5    00:00:00 sleep

如果执行 kill -15 752,不会触发 trap 直接退出

$ ./trap.sh
[TRAP]my process pid is: 2163
[TRAP]my child pid list is:
1 0
[a]my process pid is: 2164
[a]my child pid list is: 2165

如果执行 kill -15 751,触发 a.sh trap

$ ./trap.sh
[TRAP]my process pid is: 2324
[TRAP]my child pid list is:
1 0
[a]my process pid is: 2325
[a]my child pid list is: 2326
[a]ash I am going down, so killing off my processes..
kill: failed to parse argument: 'pts/5'

如果执行 kill -15 750,触发 trap.sh trap

$ ./trap.sh
[TRAP]my process pid is: 2487
[TRAP]my child pid list is:
1 0
[a]my process pid is: 2488
[a]my child pid list is: 2489
[TRAP]I am going down, so killing off my processes..

other

当脚本直接同步、异步混合使用时需要考虑周全,详细测试

Ref

  1. Shell编程之trap命令
  2. 在脚本中使用 trap

原文:大专栏  shell向子进程发送信号


以上是关于shell向子进程发送信号的主要内容,如果未能解决你的问题,请参考以下文章

将字符串发送到子进程的信号

第九章 Shell信号发送与捕捉

向守护进程发送 SIGINT

Shell脚本入门 07:进程与信号

Shell脚本入门 07:进程与信号

使用命名管道向子进程发送参数