時には、プロセスが完了したら別のコマンドを実行する必要があることに気づきます。同じシェルにある場合(そして-Zを制御できます)すでに実行中のprog1に「&& prog2」を追加できますか?多くの良い解決策が提供されています。しかし、子プロセスの場合にのみ機能します。。
少なくとも同じユーザーIDを共有するプロセスにはかなり標準的なイディオムがあります。これはシェルで次のようになります。
while kill -s 0 $pid 2> /dev/null; do sleep 1; done
/proc
Linuxなどのシステムでは、[ -d /proc/$pid ]
代替を使用してkill
同じユーザーID要件を免除できます。
しかし、どちらも競争条件があります。その間、プロセスは終了し、sleep
新しいプロセスは同じPIDを取得できます。したがって、ループは、関心のあるプロセスが実際に終了したことを認識しないまま継続します。
シェルスクリプトから競合状態を削除する方法はありますか?
ベストアンサー1
Linux によって異なる場合もあれば、他の場合は/proc
動作が異なる場合もありますが、Linux では次のことができます。
( # subshell to preserve CWD
cd /proc/$pid || exit
[ "$expected_path" = "$(readlink exe)" ] || exit # optional, and can do more checks
while [ -d . ]; do sleep 1; done
)
.
プロセスが終了すると、作業ディレクトリは無効になり、もう存在しません。しかし、新しいプロセスがそのpidを採用した場合いいえ再び有効です。プロセスが以前に終了した場合(そしてpidが未使用のままである場合)、cd
これはcd
失敗し、サブシェルは終了します。以前にpidを再利用した場合はcd
成功しますが、「オプションの」チェック(LJKimsに感謝します)でこれをキャッチできることを願っています。したがって、検査が可能な競合の非常に短い範囲を捕捉する限り、競合条件はない。テストするには、次のものを使用できます。
# shell 1
$ sleep 10 &
[1] 26453
$ cd /proc/26453
# shell 2 (must be bash for BASHPID)
for ((i=0; i<200000; ++i)) do ( if [ 26453 -eq $BASHPID ]; then echo "I am have the pid — sleeping 60"; sleep 60; echo "done sleeping"; fi ); done
I have the pid — sleeping 60
# back to shell 1
[ -d . ]; echo $?
1
したがって、新しいPIDが26453であっても、興味のある睡眠が終了したことがまだわかります。