bash 中的 SIGINT 和进程替换

SIGINT and process substitution in bash

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

#!/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 是否可能是解决方案,但它会立即退出。)

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

您可以通过添加 trap : SIGINT:

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