bash で開始されたバックグラウンド プロセスが stdout を画面に印刷するのはなぜですか?

bash で開始されたバックグラウンド プロセスが stdout を画面に印刷するのはなぜですか?

自分の状況を理解するのが難しく、これまでのところ Google はあまり役に立ちませんでした。

bash バックグラウンド ジョブを開始しました:

ping google.com &

まずプロセス ID を取得し、次に Bash が stdout を画面に出力します。

user@host:~$ ping google.com &
[1] 14004
user@host:~$ PING google.com (173.194.44.66) 56(84) bytes of data.
64 bytes from ham02s14-in-f2.1e100.net (173.194.44.66): icmp_seq=1 ttl=54 time=26.3 ms
64 bytes from ham02s14-in-f2.1e100.net (173.194.44.66): icmp_seq=2 ttl=54 time=27.4 ms
64 bytes from ham02s14-in-f2.1e100.net (173.194.44.66): icmp_seq=3 ttl=54 time=29.2 ms
...

これは今日読んだこととすべて矛盾しています。私は、GNU bash バージョン 4.3.30(1)-release (x86_64-pc-linux-gnu) を実行する標準の Debian Jessie セットアップを持っています。

誰かこれを説明してくれませんか? ありがとう。

答え1

デフォルトでは、少なくとも POSIX 準拠のシステムでは、 を使用してバックグラウンドでコマンドを実行すると、&のみが切り離されるstdinため、他のコマンドを実行できるようになります。stdoutおよび は、stderr親シェルにまだ接続されています。

stdoutおよび/またはを表示したくない場合は、stderrそれらをファイルにリダイレクトするか、次のようにします/dev/null

command &>log.txt &                #stdout and stderr to log.txt
command 1>/dev/null &               #stdout to /dev/null, stderr still attached to shell
command 1>output.log 2>error.log &  #stdout to output.log, stderr to error.log

答え2

バックグラウンド プロセスの stdout をターミナルに表示するかどうかは、ユーザー次第です。sttyユーティリティを使用して動作を変更できます。

デフォルトでは、バックグラウンド プロセスが端末に書き込むことができます。

$ echo Hello &
[1] 25850
Hello
$

この動作は次のコマンドで変更できますstty

$ stty tostop
$ echo Hello &
[2] 25873

[2]+  Stopped                 echo Hello
$ 

を指定するとtostop、バックグラウンド プロセスは stdout への書き込みを試行するときに停止します。続行を許可する場合は、フォアグラウンドに戻すことができます。

$ fg
echo Hello
Hello
$

元に戻すには、 を実行しますstty -tostop。これを実行した後、新しい作成されたバックグラウンド ジョブは、stdout に書き込むことができます。(既存のジョブには影響しません。)

ドキュメンテーション

man sttyこのtostopオプションは次のように説明されています。

* [-]tostop
端末への書き込みを試みるバックグラウンドジョブを停止します

上記の先頭は、*このオプションが非 POSIX であることを識別するため、マニュアル ページで使用されます。

関連情報