背景

背景

背景

我读过一篇邮政关于信号的处理SIGINT,但我仍然不明白如何在代码中正确处理它,这些代码将由交互式和非交互式 shell 获取和使用。

我将给出我的脚本的简化示例,并针对特定部分提出问题。


例子

我有一个具有有用功能的脚本,可以在任何地方获取和使用。

/tmp/useful_functions.sh

#!/bin/bash

function example()
{
    echo "Main script started"

    # Make process run forever in the background.
    ( while sleep 1; do echo "Background script running"; done ) &

    # Make subshell work for 10 seconds.
    local output="$(sleep 10; echo "Subshell completed")"
    echo "${output}"

    # Kill the backgrounded process once the subshell has finished.
    { kill "${!}" && wait "${!}"; } &> /dev/null

    echo "Main script completed"
}

测试1

让我们使用例子在另一个脚本中运行。

/tmp/test.sh

#!/bin/bash

source /tmp/useful_functions.sh

example

现在让我们在 subshel​​l 工作时运行/tmp/test.sh并按下。 (子外壳 = )Control-C
$(sleep 10; echo "Subshell completed")

由于。。。导致的结果Test 1

/tmp/test.shexamplesubshell进程background已终止。
提示正在等待新输入。

问题

  1. SIGINT进程之间发送/处理/传播的顺序是什么?
    (提到SIGINT应发送至所有前景进程,并且最内部的进程应该首先处理它。)
  2. 为什么后台进程被终止?

测试2

让我们使用例子直接在交互式 Bash 中运行:

...$ source /tmp/useful_functions.sh
...$ example

Control-C当 subshel​​l 工作时再次按下。
(子外壳 = $(sleep 10; echo "Subshell completed")

由于。。。导致的结果Test 2

example进程subshell已终止,但backgrounded进程仍保持活动状态。即使打印了进程
的输出,提示仍在等待新的输入。backgrounded

问题

  1. SIGINT进程之间发送/处理/传播的顺序是什么?
  2. 为什么后台进程现在没有终止?

改进示例

尽管我不完全理解 的行为Test 1,但这种行为是我所期望的,我也想通过交互式 Bash 来实现这一目标。
想法是创建另一个子 shell,它包装后台进程和现有子 shell,并希望新进程的终止将导致后台进程和现有子 shell 的终止。

/tmp/useful_functions.sh

#!/bin/bash

function example()
{
    (
        echo "Main script started"

        # Make process run forever in the background.
        ( while sleep 1; do echo "Background script running"; done ) &

        # Make subshell work for 10 seconds.
        local output="$(sleep 10; echo "Subshell completed")"
        echo "${output}"

        # Kill the backgrounded process once the subshell has finished.
        { kill "${!}" && wait "${!}"; } &> /dev/null

        echo "Main script completed"
    )
}

重复的结果Test 1

/tmp/test.shexampleouter subshellinner subshell进程background已终止。
提示正在等待新输入。

问题

  1. SIGINT进程之间发送/处理/传播的顺序是什么?
  2. 为什么后台进程被终止?

重复的结果Test 2

exampleouter subshellinner subshell进程background已终止。
提示正在等待新输入。

问题

  1. SIGINT进程之间发送/处理/传播的顺序是什么?
  2. 为什么后台进程被终止?

问题

此时我意识到我实际上必须在后台进程之后进行一些清理,并且我需要捕获SIGINT某个地方来处理它。

解决方案

因为我不知道SIGINTBash 中一般是如何处理和传播的,所以我做了一些有根据的猜测,并提出了我认为可以正常工作的解决方案,但不能确定。

#!/bin/bash

function example()
{
    (
        echo "Main script started"

        # Make process run forever in the background.
        (
            trap "echo Cleanup; trap - SIGINT; kill -s SIGINT ${$}" SIGINT
            while sleep 1; do echo "Background script running"; done
        ) &

        # Make subshell work for 10 seconds.
        local output="$(sleep 10; echo "Subshell completed")"
        echo "${output}"

        # Kill the backgrounded process once the subshell has finished.
        { kill "${!}" && wait "${!}"; } &> /dev/null

        echo "Main script completed"
    )
}

问题

  1. 我的陷阱能正确处理/传播SIGINT吗?
  2. ${$}正确的流程吗?
    (在提到的帖子中,据说该进程应该杀死自己,但他们的示例使用${$}而不是${BASHPID}。)

相关内容