【问题标题】:shell script with trapped signal does not ignore signal带有捕获信号的 shell 脚本不会忽略信号
【发布时间】:2020-02-05 17:16:58
【问题描述】:

我正在开发一个测试自动化系统,但我想出了一些行为不端的程序。对于第一个,我已经遇到了一些意想不到的行为。

    trap "echo No thanks" INT                            

    echo Let me just chill for $1 sec  
    sleep $1                                     
    echo All finished

观察到的行为:

  • 发送 SIGINT 会导致打印“不,谢谢”,睡眠显然会立即中断,之后也会立即打印“全部完成”。
  • 无论信号是单独发送还是使用键盘 ctrl+c 执行,行为都是相同的。
  • 如果睡眠是后台的,我们会wait 为它观察到相同的行为。

预期行为:

  • 向进程发送 SIGINT 应该会在睡眠运行期间打印“不,谢谢”,然后在睡眠结束后退出之前打印“全部完成”。
  • 如果睡眠是后台的,发出键盘 ctrl+c 应该发送 SIGINT 到进程组,这将包括睡眠,所以应该过早停止它。我不知道会发生什么

问题:

  • 如何获得所需的行为?
  • 为什么它的行为是这样的(与我的预期不同)?

这个问题本质上是 this 的欺骗,但该答案没有令人满意的解释。

【问题讨论】:

  • 你试过echo "No thanks" && exit吗?您还可以调用一个函数,该函数将在最后回显和。有时您希望程序在捕获信号时继续运行(例如,显示信号 USR1 的统计信息)。
  • @Matthieu 请重新阅读问题,关键是让它不退出,但它正在意外退出
  • 如果我将信号单独发送到bash 进程,直到sleep 完成后我才会看到陷阱执行。 Control-C 不同,因为组中的每个进程都直接从操作系统接收信号。
  • 您的预期不正确 — the trap handler will be run after the foregrounded sleep completes。此外,也许你正在杀死错误的 PID。没有人可以重现您报告的行为,下面的答案是针对您说您没有做的 Ctrl-C 案例。你能告诉我们你是如何准确地输入什么来知道要杀死的 pid,你看到了什么,以及你输入了什么是如何杀死它的吗?
  • 是的,但问题是,control+c 会杀死对照组。所以sleep 也收到了SIGINT。因为sleep 接收到SIGINT,所以它终止,然后因为 bash 也接收到 SIGINT,所以它运行处理程序。

标签: linux bash unix process


【解决方案1】:

目前:

  1. bash 等待 sleep 退出
  2. bashsleep 接收信号
  3. sleep 死了
  4. bash 完成等待并运行陷阱

这会阻止您想要的行为,因为:

  • 你不想sleep
  • 您不希望 bash 在运行陷阱之前等待命令完成

要解决此问题,您可以让sleep 忽略信号,并让bash 在循环中运行wait,以便主脚本在ctrl-c 之后重新获得控制权,但仍等待@987654334 @完成:

trap 'echo "No thanks"' INT
echo "Let me just chill for $1 sec"
# Run sleep in the background
sleep "$1" &
# Loop until we've successfully waited for all processes
until wait; do true; done
echo "All finished"

【讨论】:

  • 陷阱不被子shell继承。只需sleep $1 &Feel free to remove it and try - 有无使用都一样。
  • 哦,差异可能取决于后台进程是否在同一个进程组中并且也接收sigint。
  • 陷阱使子shell忽略SIGINT,但您不需要在子shell中执行。 sleep,在后台处理时,不会收到 SIGINT(不知道为什么,但我认为后台处理作业会将其移出当前进程组)。
  • 这段代码的行为如我所愿。它在收到信号后立即运行陷阱。现在只要能解释为什么等待会被信号打断就好了。我认为解释在这里的某个地方:cons.org/cracauer/sigint.html
  • From pubs.opengroup.org/onlinepubs/9699919799/utilities/… "当 shell 通过等待实用程序等待异步命令完成时,接收已设置陷阱的信号将导致等待实用程序立即返回退出状态 >128,之后立即执行与该信号相关的陷阱。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-24
  • 2015-05-03
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多