【问题标题】:SIGINT and process substitution in bashbash 中的 SIGINT 和进程替换
【发布时间】:2022-01-04 10:59:21
【问题描述】:

我发现如果我有类似的东西:

#!/usr/bin/env bash

function abort-politely {
  echo 'Aborting politely'
  {
    sleep 5
    touch .stop
  }
}
trap 'abort-politely' SIGINT

{
  while [ ! -r .stop ] ; do echo hello world ; sleep 1 ; done
  rm -f .stop
} &
wait $!

echo Exiting

它的行为和我预期的一样,也就是说后台任务在中断后会持续5s:

hello world
hello world
hello world
hello world
<Ctrl+C pressed>
Aborting politely
hello world
hello world
hello world
hello world
hello world
Exiting

但是,如果我将 process substitution 作为后台进程的一部分引入...

#!/usr/bin/env bash

function abort-politely {
  echo 'Aborting politely'
  {
    sleep 5
    touch .stop
  }
}
trap 'abort-politely' SIGINT

{
  # The "while" loop below is all that has changed
  while [ ! -r .stop ] && read line; do echo hello $line ; done < <(
    while : ; do echo world ; sleep 1 ; done
  )
  rm -f .stop
} &
wait $!

echo Exiting

...当按下 Ctrl+C 时,后台进程似乎立即退出:

hello world
hello world
hello world
hello world
<Ctrl+C pressed>
Aborting politely
<5 seconds delay>
Exiting

我期待与第一种情况相同的输出。

这怎么不像我预期的那样工作?有没有办法让它像我希望的那样表现?我想我需要的是进程替换继续进行,直到不再被读取。 (我想知道在进程替换块中添加trap '' SIGINT 是否可能是解决方案,但它会立即退出。)

【问题讨论】:

    标签: bash process sigint


    【解决方案1】:

    SIGINT 信号通过子进程传播,导致进程替换 shell 自行中止。

    你可以通过添加trap : SIGINT来避免它:

      while [ ! -r .stop ] && read line; do echo hello $line ; done < <(
        trap : SIGINT
        while : ; do echo world ; sleep 1 ; done
      )
    

    【讨论】:

    • 谢谢!奇怪的是,这似乎与我最初尝试的完全一样:trap '' SIGINT 但是当我运行它们时它们都立即退出。我现在意识到这可能是由于之前运行的流氓.stop 文件造成的!当我重新运行它时,它工作正常。所以无论如何,你的解决方案让我得到了答案,所以即使它与我之前尝试过的基本相同,也应该被标记为正确!奇怪的是,它在打印“Exiting”并退出后打印了一个额外的“hello world”。不知道为什么会这样。
    • 这可能只是响应延迟问题。
    猜你喜欢
    • 1970-01-01
    • 2011-05-28
    • 2018-04-11
    • 2013-11-07
    • 2023-04-06
    • 2014-09-08
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    相关资源
    最近更新 更多