web-dev-qa-db-ja.com

サブシェルの奇妙な動作のバックグラウンドプロセス

なぜいくつかの同様のbashコマンドがそれらのように動作するのだろうか。

私はbashスクリプトを持っていますfoo

#!/usr/bin/env bash

while true
do
    echo "reading"
    read data
    echo $data
    echo "stderr msg" >&2
    sleep 1
done

これは、stdinから一度に1行を読み取り、同じ行を出力する無限ループです。 bashスクリプトもありますbar

#!/usr/bin/env bash

./foo &

次のコマンドは、Ubuntu18.04のターミナルのbash(v。4.4.19)で実行されました(スクリプトが作業ディレクトリにあると仮定します)。

  1. ./foo &

    • この回答 に従って、stdinから読み取ろうとすると停止します。

    • 予想通り、制御端末が強制終了されると強制終了されます。

  2. (./foo &)

    • Stdinからの新しい入力が自動的に継続的に供給されているように見えます。 stdinから読み込もうとしたときに、停止しすぎてはいけませんか?取得したものが何であれ、エコーされたときに表示されないので、EOF文字だと思います。

    • 制御端末が強制終了された後も実行を継続します。 psの出力を見ると、制御端末がpts /xから?に変わります。 disownまたはNohupを使用せずに、これはどのように発生しましたか? (ただし、元の制御端末を強制終了した後、書き込みごとに「書き込みエラー:入出力エラー」が発生します。これは、そのstdoutが現在閉じている端末に関連付けられているためだと思います。正しいですか?)

  3. bash -c "./foo &"

    2)とまったく同じように動作するように見えます。

  4. ./bar

    2)および3)とまったく同じように動作するように見えます。

  5. スタートアップアプリケーションとしてbash -c "~/foo"&なし)を追加する

    2)、3)、4)と同様に動作しますが、次の違いがあります。

    • その制御端末はデスクトップttyxです。
    • 制御端末を強制終了することはできません(できますか?)。

    これらの違いはどれも私には奇妙に思えませんが、新しい入力が継続的に供給されているという事実だけです。

私の推測では、2)-5)はすべて、stdinが/dev/nullのようなものにリダイレクトされる種類のサブシェルを使用していますが、私は非常に確信がなく、より正確な答えを探しています。

1
gblomqvist

シェルなしでジョブ制御を有効にして(たとえば、スクリプトまたは&サブシェルで)(...)を使用して実行されるコマンドには、 /dev/nullおよびSIGINTおよびSIGQUITからリダイレクトされたstdinはSIG_IGNに設定されます。 susv4から 標準

ジョブ制御が無効になっている場合(set-mを参照)、明示的なリダイレクトが実行される前の非同期リストの標準入力は、同じプロパティを持つファイルに割り当てられていると見なされます。 /dev/nullとして。ジョブ制御が有効になっている場合、これは発生しません。すべての場合において、標準入力の明示的なリダイレクトは、このアクティビティをオーバーライドするものとします。

this および this も参照してください。

./fooスクリプトが「継続的に供給される」データであるというのは真実ではありません-/dev/nullから読み取ろうとするとEOF)を取得します-終了ステータスを確認する必要がありますreadの。

1
mosvy

サブシェルは非対話型です。インタラクティブシェルのみが自動的に強制終了されます。

0
user1133275