背景

背景

背景

私は記事を読んだ郵便はがき信号処理に関して、SIGINT対話型シェルと非インタラクティブシェルの両方で選択し、使用するコードで信号を正しく処理する方法はまだ理解されていません。

私のスクリプトの簡単な例を見て、特定の部分について質問します。


はい

どこでも入手して使用できる便利な機能を備えたスクリプトがあります。

/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

それでは、サブシェルが動作している間に実行して/tmp/test.sh押してみましょう。 (サブシェル=)Control-C
$(sleep 10; echo "Subshell completed")

なぜなら。 。 。結果Test 1

/tmp/test.sh、、、プロセスexampleが終了しました。 プロンプトが新しい入力を待っています。subshellbackground

質問

  1. SIGINTプロセス間転送/処理/伝播の順序は何ですか?
    (メンションはSIGINT次のアドレスに送信する必要があります。すべての視聴者最も内側のプロセスは最初に処理する必要があります。 )
  2. バックグラウンドプロセスが終了するのはなぜですか?

テスト2

使用しようはいインタラクティブBashで直接実行する:

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

Control-Cサブシェルが機能したら、もう一度押します。
(サブシェル= $(sleep 10; echo "Subshell completed")

なぜなら。 。 。結果Test 2

exampleプロセスはsubshell終了しましたが、backgroundedプロセスはアクティブのままです。プロセスの出力が印刷されても、
プロンプトはまだ新しい入力を待っています。backgrounded

質問

  1. SIGINTプロセス間転送/処理/伝播の順序は何ですか?
  2. バックグラウンドプロセスが今終了しないのはなぜですか?

改善された例

動作を完全には理解していませんが、Test 1この動作は私が期待する動作であり、インタラクティブなBashでこれを達成したいと思います。
バックグラウンドプロセスと既存のサブシェルを包む別のサブシェルを作成し、新しいプロセスが終了すると、バックグラウンドプロセスと既存のサブシェルも終了することを望むアイデアです。

/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.shexampleおよびプロセスがouter subshell終了しました。プロンプトが新しい入力を待っています。inner subshellbackground

質問

  1. SIGINTプロセス間転送/処理/伝播の順序は何ですか?
  2. バックグラウンドプロセスが終了するのはなぜですか?

重複した結果Test 2

example、、、プロセスouter subshellが終了しました。 プロンプトが新しい入力を待っています。inner subshellbackground

質問

  1. SIGINTプロセス間転送/処理/伝播の順序は何ですか?
  2. バックグラウンドプロセスが終了するのはなぜですか?

質問

SIGINTこの時点で、私は実際にバックグラウンドプロセスの後にクリーンアップを行う必要があることと、それを処理するどこかにキャプチャする必要があることに気づきました。

解決策

私はBashで一般的に処理と伝播がどのように行われているのか分からないので、SIGINT知識に基づいた推測を行い、効果があると思いましたが、わからない解決策を思い出しました。

#!/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}。)

ベストアンサー1

おすすめ記事