別のシェルで開始されたプログラムを待つ方法


20

私は、動作するすべてのデータが使用可能になったときにcronによって開始される大量の作業(約4〜5時間かかる)を行うプログラムを持っています。時々、それが終了するのを待っているときに、終了時に別の(インタラクティブ)プログラムを開始したいことがあります。待機コールは有望に見えますが、子供を待つだけです。


私が考えることができる他の唯一の方法は、cronjobからファイルを作成し、そのプロセスでinotifywaitを使用することです。ファイルが削除されると、2番目のプロセス(inotifywaitを実行)を開始できます。
slm

ipc同様に、プロセス間通信を使用して、これらのラインに沿って何かを行うことができると思います。man ipc
slm

サービスを再起動するのを見ていませんが、このQ&Aで言及されているGod、Monit、または他のパッケージのいずれかがジョブを実行します。unix.stackexchange.com
slm

@slmは、たとえば/ proc / _pid_ / fd / 1のclose_writeで待機するなど、どのファイルシステムでもinotifyを使用できますか?
13

完全には定かではありませんが、それは別の方法かもしれません8-)。inotifywait(ファイル用)に似たプロセス監視に関連するいくつかの新しいカーネル機能があった場所を覚えているQがありました。この新しい機能は、プロセス中のイベント用でしたが、Q&Aの多くは私の頭の中で一緒に実行されるようになると思いました8-)。Aは私またはGillesによって提供されたと思います。
slm

回答:


13

私は間違いなくEDIT#3ソリューションを好みます(以下を参照)。

同じシェルにない場合は、ps -pが trueを返す条件でwhileループを使用します。入れて睡眠をプロセッサの使用量を減らすためにループで。

while ps -p <pid> >/dev/null 2>&1
do
   sleep 10
done 

または、UNIXが/ procをサポートしている場合(たとえば、HP-UXはまだサポートしていません)。

while [[ -d /proc/<pid> ]]
do 
    sleep 10
done

タイムアウトが必要な場合

timeout=6  # timeout after 1mn  
while ((timeout > 0)) && ps -p <pid> >/dev/null 2>&1
do
   sleep 10
   ((timeout -= 1))
done 

編集#1

他の方法があります:cronを使用しないでください。batchコマンドを使用して、ジョブをスタックします。

たとえば、すべてのジョブを毎日スタックできます。バッチは、ブロックされたジョブがすべてのスタックを停止しないように並列性を許可するように調整できます(オペレーティングシステムによって異なります)。

編集#2

ホームディレクトリにfifoを作成します。

$ mkfifo ~/tata

あなたの仕事の終わりに:

echo "it's done" > ~/tata

他のジョブ(待機中のジョブ)の開始時:

cat ~/tata 

古い良いIOをブロックすることはポーリングしていません。

編集#3

信号を使用する:

待機しているスクリプトの開始時に:

echo $$ >>~/WeAreStopped
kill -STOP $$

あなたの長い仕事の終わりに:

if [[ -f ~/WeAreStopped ]] ; then
    xargs kill -CONT < ~/WeAreStopped
    rm ~/WeAreStopped
fi

ポーリング、うん!素敵な決定:プロセッサ時間または睡眠を調整するための私の時間を無駄にします。より良い答えが必要です。
13

:)ポーリングはあなたに適しています。ポーリングはステートレスで、ポーリングは信頼できます。
エマニュエル

ポーリングは遅く、ポーリングはプロセッサ時間を浪費します。
13

実行時間が0.01秒の場合、4時間の間に実行された1440 psは14.4秒を消費します。はるかに少ないジョブの依存関係を管理スケジューラより:D
エマニュエル・

これはおそらく最良のオプションだと思います:それはハックですが、stackoverflow.com / questions / 1058047 /…。
slm

5

cronジョブを変更して、フラグを使用できます。

の代わりに

2  2 * * *           /path/my_binary

使用できます

2  2 * * *           touch /tmp/i_m_running; /path/my_binary; rm /tmp/i_m_running

このファイルをスクリプトで監視するか、手動で監視するだけです。存在する場合、プログラムは実行中です。それ以外の場合は、何でも自由に実行できます。

スクリプトサンプル:

while [[ -f /tmp/i_m_running ]] ; do
   sleep 10 ;
done
launch_whatever_you_want

を使用したくない場合はsleep、スクリプトを変更し、X分に1回、cronを介して実行できます。

その場合、スクリプトサンプルは次のようになります。

[[ -f /tmp/i_m_running ]] && { echo "Too early" ; exit ; }
launch_whatever_you_want

この方法は、cronプロセスのPIDを見つける必要がないため、少し簡単です。


4

親が子プロセスの1つが終了するのを待つことを除いて、プロセスが別のプロセスの終了を待つ機能はありません。可能であれば、スクリプトを使用してプログラムを起動します。

do_large_amount_of_work
start_interactive_program

たとえば、cronジョブから大量の作業を開始したいが、セッションのコンテキストから対話型プログラムを開始する前に、それができない場合は、次のようにします。

do_large_amount_of_work
notify_completion

実装する方法はいくつかありますnotify_completion。一部のデスクトップ環境は、通知メカニズムを提供します(リモートXディスプレイでウィンドウを開きます(「ディスプレイを開けない」理由)?)。ファイル変更通知を使用して作成することもできます。Linuxでは、ファイル変更通知機能はinotifyです。

do_large_amount_of_work
echo $? >/path/to/finished.stamp

の作成に反応するには/path/to/finished.stamp

inotifywait -e close_write -q /path/to/finished.stamp
start_interactive_program

do_large_amount_of_work起動方法を変更できないが、最後に変更するファイルがわかっている場合は、同じメカニズムを使用して、そのファイルが閉じられたときに反応することができます。ファイルの名前変更など、他のイベントに対応することもできます(inotifywait可能性のリストについては、マニュアルを参照してください)。


0

cronjobによってトリガーされるスクリプトに空のシェルスクリプトを呼び出して、必要に応じてフォローアップタスクを挿入できます。

これは、Gillesのアプローチに非常に似ています。

cronjob-task.sh 含まれるもの:

# do_large_amount_of_work

./post-execute.sh

ここpost-execute.shは、フォローアップタスクをトリガーする必要があることがわかっていない限り、通常は空です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.