パイプとコマンドについて私が理解したように、bashは各コマンドを取り、各コマンドのプロセスを生成し、前のコマンドの標準出力を次のコマンドの標準入力に関連付けます。
例えば、「ls -lsa | grep feb」では、bashは2つのプロセスを生成し、「ls -lsa」の出力を「grep feb」の入力に接続します。
Bashで「sleep 30&」などのバックグラウンドコマンドを実行すると、そのコマンドを実行するバックグラウンドプロセスのpidが得られます。驚くべきことに、"ls -lsa | grep feb &"と書くと、bashは1つのPIDだけを返します。
これをどのように説明しますか? 「ls -lsa」と「grep feb」を同時に実行するプロセスは1つありますか?複数のプロセスが作成されましたが、そのうちの1つだけpidを取得しますか?
答え1
バックグラウンドでジョブを実行すると、bashは子プロセスのプロセスID、つまりジョブで実行されているコマンドのプロセスIDを印刷します。タスクがより多くの子プロセスを生成する場合、親シェルとは何の関係もありません。
something1 | something2 &
バックグラウンドジョブがパイプライン(eg以外の形式のコマンドなど{ something1 | something2; } &
)の場合は、POSIXで強くお勧めし、bashを含むほとんどのシェルで実行される最適化があります。パイプラインの各要素は、次のサブプロセスとして直接実行されます。元の殻。 POSIXの要件は変える$!
この場合、パイプラインの最後のコマンドに設定されます。ほとんどのシェルでは、最後のコマンドはパイプラインの他のコマンドと同様に元のプロセスのサブコマンドです。
を実行すると、ls -lsa | grep feb
3つのプロセスが関係します。パイプの左側を実行するプロセス(パイプ設定を完了してから実行するサブシェル)、パイプls
の右側を実行するプロセス(パイプを完成するサブシェル)を設定した後に実行grep
)、スタンバイパイプライン完了の元のプロセス。
プロセスを追跡して進行状況を観察できます。
$ strace -f -e clone,wait4,pipe,execve,setpgid bash --norc
execve("/usr/local/bin/bash", ["bash", "--norc"], [/* 82 vars */]) = 0
setpgid(0, 24084) = 0
bash-4.3$ sleep 10 | sleep 20 &
…
sleep
2番目の項目がどのように報告され保存されているかを確認してください$!
。ただし、プロセスグループIDは最初のエントリですsleep
。 Dashにkshおよびmkshにない同じ特徴があります。
答え2
2つのプロセスを作成します。&
2番目のプロセスのPIDを表示します。以下の例
$ echo $$
13358
$ sleep 100 | sleep 200 &
[1] 13405
$ ps -ef|grep 13358
ec2-user 13358 13357 0 19:02 pts/0 00:00:00 -bash
ec2-user 13404 13358 0 19:04 pts/0 00:00:00 sleep 100
ec2-user 13405 13358 0 19:04 pts/0 00:00:00 sleep 200
ec2-user 13406 13358 0 19:04 pts/0 00:00:00 ps -ef
ec2-user 13407 13358 0 19:04 pts/0 00:00:00 grep --color=auto 13358
$