競合状態なしで終了する子プロセスではなく、プロセスにシェルコマンドを関連付けるにはどうすればよいですか?

競合状態なしで終了する子プロセスではなく、プロセスにシェルコマンドを関連付けるにはどうすればよいですか?

時には、プロセスが完了したら別のコマンドを実行する必要があることに気づきます。同じシェルにある場合(そして-Zを制御できます)すでに実行中のprog1に「&& prog2」を追加できますか?多くの良い解決策が提供されています。しかし、子プロセスの場合にのみ機能します。

少なくとも同じユーザーIDを共有するプロセスにはかなり標準的なイディオムがあります。これはシェルで次のようになります。

while kill -s 0 $pid 2> /dev/null; do sleep 1; done

/procLinuxなどのシステムでは、[ -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であっても、興味のある睡眠が終了したことがまだわかります。

おすすめ記事