bash 陷阱在 shell 脚本中不起作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26858344/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:45:58  来源:igfitidea点击:

trap not working in shell script?

bashshellunixprocess

提问by jph

I'm in the process of writing a script on OS X that needs to trap SIGTERM in order to kill some child processes before exiting. For the sake of this question I've boiled it down to the following minimal example that, for some reason, isn't working as I'd expect it to:

我正在 OS X 上编写脚本,该脚本需要捕获 SIGTERM 以便在退出之前杀死一些子进程。为了这个问题,我将其归结为以下最小示例,由于某种原因,它没有像我期望的那样工作:

#!/bin/sh

function shutdown()
{
  touch foo.txt
  exit 0
}

trap shutdown TERM
su -l myusername -c "sleep 9999"

I run this script in one terminal window, then switch to another and "ps -aef" yields this:

我在一个终端窗口中运行此脚本,然后切换到另一个窗口,“ps -aef”产生以下结果:

  502   857   645   0 11:38PM ttys001    0:00.00 /bin/sh ./foo.sh
    0   858   857   0 11:38PM ttys001    0:00.02 su -l myusername -c sleep 9999
  502   859   858   0 11:38PM ttys001    0:00.00 sleep 9999

From that second window I then issue "kill -15 857", but the trap is never triggered. The script remains blocked on the "su" command.

然后我从第二个窗口发出“kill -15 857”,但从未触发陷阱。该脚本在“su”命令上仍然被阻止。

Any idea why? I get the feeling it's something simple.

知道为什么吗?我觉得这很简单。

回答by Edouard Thiel

The bash manual statesthat:

bash的手册指出的是:

If bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes.

如果 bash 正在等待命令完成并接收到设置了陷阱的信号,则在命令完成之前不会执行陷阱。

As gniourf_gniourfsays, this is a POSIX spec relative to signals in shells.

正如gniourf_gniourf所说,这是与 shells 中的信号相关的 POSIX 规范。

You can check it by trapping for instance SIGUSR1 in place of SIGTERM; you'll see that kill -TERMwill kill again the process.

您可以通过捕获例如 SIGUSR1 代替 SIGTERM 来检查它;你会看到这kill -TERM将再次终止进程。

A solution is to run the command in background, then waitfor its termination. In this case the trapwill work. Try this:

一种解决方案是在后台运行该命令,然后wait终止该命令。在这种情况下,trap将起作用。尝试这个:

#! /bin/bash

shutdown()
{
    touch foo.txt
    exit 0
}

trap shutdown TERM
su -l myusername -c "sleep 9999" &    # On Ubuntu: sudo su
wait

You will get two problems: suwon't be able to ask password in foreground; you will have to manually kill su.

你会遇到两个问题:su前台无法询问密码;你将不得不手动杀死su