この質問では:シェルスクリプトで最後に実行されたコマンドのpidを取得する方法は?
スレッドは素晴らしく明確ですが、コマンドがバックグラウンドで実行されるために実際に最後に「&」が必要でない場合はどうなりますか?では、PIDを取得できますか?
ps
注:私はandを使用したくありませんgrep
。理論的には、プロセスのPIDはコマンドの実行後に見つける必要があるため、この質問をします。
バックグラウンドアプリの例 - これは私が必要としません。独自にバックグラウンドに入るすべてのものに対する一般的な解決策が必要です(誰かが「前景」オプションがまったくないことを強制します)。ただし、ソリューションをテストするには、次の手順を実行します。すばらしく働きます:
私のアプリケーションスクリプト:
#!/bin/bash
(
sleep 10
echo test
sleep 5
) &
ご覧のとおり、「&」はスクリプトの外部ではなく内部にあるため、スクリプトの起動に & は必要ありません。
./my-app ; echo $! | od -c ; jobs | od -c
0000000 \n
0000001
0000000
$! null でjobs
何も返しません。 10秒後も「TEST」メッセージが表示され続けます。
ps x | grep my-app | grep -v grep
14986 pts/5 S 0:00 /bin/bash ./my-app
更新、bash操作がここで機能しないといういくつかの意見が出た後、解決策を探したいと思い、私の希望はbashに限定されません。
ベストアンサー1
到着背景独自に、アプリケーションは子プロセスを分岐し、親プロセスを終了します。シェルはコマンド自体を実行する前に分岐されたプロセスなので、親プロセスについて知っていますが、そのプロセスを作成できる子や孫を見る方法はありません。
これらのバックグラウンドコマンドのより簡単な例は次のとおりです。
$ sh -c 'ps -j; sleep 10 &'
PID PGID SID TTY TIME CMD
6562 6562 14469 pts/13 00:00:00 sh
6563 6562 14469 pts/13 00:00:00 ps
14469 14469 14469 pts/13 00:00:00 zsh
私はプロセスとそのプロセスグループをzsh
理解しています。sh
しかし、見えるのは6562のプロセス終了だけです。 6562プロセスが6563プロセスを作成したかどうかを知る方法はありません。
$ ps -j
PID PGID SID TTY TIME CMD
6564 6562 14469 pts/13 00:00:00 sleep
6565 6565 14469 pts/13 00:00:00 ps
14469 14469 14469 pts/13 00:00:00 zsh
ただし、実行中のプロセスも対応する6562プロセスグループにあることがわかりますsleep
(ただし、コマンドが新しいプロセスグループまたはセッションを開始するのをやめる方法はありません(通常はデーモンが実行するように)。
これらのプロセスグループは、シェルの相互作用中にのみ作成されます。
あなたができるもう一つのことは次のとおりです。
cmd | cat &
wait
cmdによって生成されたプロセスが標準出力を閉じない限り、cat
すべてが死ぬまで死ぬことはありません。