
バックグラウンドでbashを介して長期実行パイプラインを実行しています。
find / -size +500M -name '*.txt' -mtime +90 |
xargs -n1 gzip -v9 &
パイプラインの2番目のステップは、大きくて古いファイルが複数あるため、完了するのに時間がかかります。
代わりに、パイプラインの最初の部分がすぐに完了し、パイプラインがいっぱいになることなく完了するため、find
正常に終了します。
親プロセスが子プロセスに適しているbash
ようです。wait
find
次のいずれかの方法で実行される(pid 20851)がないため、これを行うことができます。
ps alx | grep 20851
pgrep -l find
ゾンビプロセスがなく、20851
プロセスIDを持つプロセスがシステムのどこにも見つかりませんでした。
Bashの組み込み機能は、jobs
プロセスIDなしでタスクを1行で正しく表示します。
[1]+ Running find / -size +500M -name '*.txt' -mtime +90 | xargs -n1 gzip -v9 &
/bin/jobs
OTOH:偶然次のような別々のジョブ制御コマンド()を見つけました。
[1]+ 20851 Running find / -size +500M -name '*.txt' -mtime +90
20852 Running | xargs -n1 gzip -v9 &
そして(間違って)終了した20851
検索プロセスを「実行中」とマークします。
これはCentOS(編集:より正確には:Amazon Linux 2 AMI
)Linuxにあります。これは/bin/jobs
2行のスクリプトであることがわかりました/bin/sh
。
#!/bin/sh
builtin jobs "$@"
私はこれが私を驚かせた。別のプログラム( )で開始された別のプロセスは、そのプロセスが完了して終了し、ゾンビプロセスではなく、他のプログラムsh
()が管理するプロセスの内容をどのように知ることができますか?bash
pid
追加:システムの他のメソッド(ps
、)が不明なpgrep
場合は、終了したプロセス(含む)の詳細をどのように知ることができますか?
編集する:
(1) Billy 叔父さんがコメントで指摘したように、このシステムでは と は/bin/sh
同じ/bin/bash
ですが(/bin/sh
へのシンボリックリンク/bin/bash
)/bin/jobs
シャバンラインがあるスクリプトなので、別のプロセスで実行されます。
(2)また、ビリーのおじさんのおかげで繁殖が容易になりました。/bin/jobs
これは赤ニシンです。私はそれが出力を生成するものだと誤って考えました。jobs
驚くべき出力は、次のように呼び出されたときにbash組み込み関数から来たようです-l
。
$ sleep 1 | sleep 3600 &
[1] 13616
$ jobs -l
[1]+ 13615 Running sleep 1
13616 Running | sleep 3600 &
$ ls /proc/13615
ls: cannot access /proc/13615: No such file or directory
したがって、プロセス13615は存在しませんが、bash組み込みジョブ制御によって「実行中」とマークされますjobs -l
。
その存在は/bin/jobs
私を混乱させ、それが犯人であるに違いないと思って(いいえ)、混乱して疑わしく見えます。私はそれが役に立たないので、システムから削除する必要があると思います(とにかくsh
呼び出し元のタスクを表示できない別のプロセスで実行されるスクリプト)。
答え1
FWIW、次の方法であなたのケースを再現します。
rhel8$ /bin/jobs(){ jobs -l; }
rhel8$ sleep 1 | sleep 3600 &
[1] 2611
rhel8$ sleep 2
rhel8$ jobs
[1]+ Running sleep 1 | sleep 3600 &
rhel8$ /bin/jobs
[1]+ 2610 Running sleep 1
2611 Running | sleep 3600 &
rhel8$ pgrep 2610
<nothing!>
rhel8$ ls /proc/2610
ls: cannot access '/proc/2610': No such file or directory
rhel8$ /bin/jobs
[1]+ 2610 Running sleep 1
2611 Running | sleep 3600 &
rhel8$ cat /bin/jobs
#!/bin/sh
builtin jobs "$@"
または、以下を使用してください(以前よりはるかに悪い)。
rhel8$ unset -f /bin/jobs
rhel8$ export JOBS=$(jobs -l)
rhel8$ builtin(){ echo "$JOBS"; }
rhel8$ export -f builtin
rhel8$ /bin/jobs
[1]+ 2610 Running sleep 1
2611 Running | sleep 3600 &
rhel8$ type /bin/jobs
/bin/jobs is /bin/jobs
注:すでに説明したように、jobs -l
bashは終了したパイププロセスの古い情報を表示し続けますRunning
。 IMHO これはバグです。他のシェル(例:zsh、ksh、またはyash)ではこれをDone
。