別のプログラムを使用してDB接続を確立しようとするスクリプトがあり、プログラムのタイムアウト(2.5分)が長すぎます。この機能をスクリプトに追加したいと思います。
接続に5秒以上かかる場合は、プロセスを終了します
それ以外の場合は、スリープ/キルプロセスを終了します。
私が抱えている問題は、プロセスが強制終了されたときにbashがどのようにレポートするかです。これは、プロセスが同じシェルにバックグラウンドで存在するためです。これを行うためのより良い方法はありますか、またはkillコマンドのシェルをサイレントにするにはどうすればよいですか?
DB_CONNECTION_PROGRAM > $CONNECTFILE &
pid=$!
(sleep 5; kill $pid) &
sleep_pid=$!
wait $pid
# If the DB failed to connect after 5 seconds and was killed
status=$? #Kill returns 128+n (fatal error)
if [ $status -gt 128 ]; then
no_connection="ERROR: Timeout while trying to connect to $dbserver"
else # If it connected kill the sleep and any errors collect
kill $sleep_pid
no_connection=`sed -n '/^ERROR:/,$p' $CONNECTFILE`
fi
同じかどうかはわかりませんが、数年前に同様の問題を修正しました。しかし、私はプログラマーであり、Unixのようなシステム管理者ではないので、私のBash-fuはそれほど強力ではない可能性があるので、以下を塩味でお試しください...
基本的に私はフォーク、フォーク、フォークをしました:)
Out of memory 私の古いコード(私は驚くほど毎日毎日使用しています)を見つけた後、私のメモリが十分ではなかったため、Bashでは次のように機能しました。
commandThatMayHang.sh 2 > /dev/null 2>&1 & (notice that last '&', we're forking)
MAYBE_HUNG_PID=$!
sleepAndMaybeKill.sh $MAYBE_HUNG_PID 2 > /dev/null 2>&1 & (we're forking again)
SLEEP_AND_MAYBE_KILL_PID=$!
wait $MAYBE_HUNG_PID > /dev/null 2>&1
if [ $? -eq 0 ]
# commandThatMayHand.sh did not hang, fine, no need to monitor it anymore
kill -9 $SLEEP_AND_MAYBE_KILL 2> /dev/null 2>&1
fi
ここで、sleepAndMaybeKill.shは、必要な時間だけスリープしてから、commandThatMayHand.shを強制終了します。
したがって、基本的に2つのシナリオは次のとおりです。
コマンドは正常に終了し(5秒のタイムアウト前など)、waitコマンドが正常に終了するとすぐに停止します(「キラー」は不要になったため、強制終了します)
コマンドがロックし、キラーがコマンドを強制終了する
いずれの場合も、コマンドが完了するとすぐに成功するか、タイムアウト後に失敗することが保証されます。
GNUタイムアウトと呼ばれるcoreutilsユーティリティがあります: http://www.gnu.org/s/coreutils/manual/html_node/timeout-invocation.html
あなたのプラットフォームでそれを持っているなら、あなたはそうすることができます:
timeout 5 CONNECT_TO_DB
if [ $? -eq 124 ]; then
# Timeout occurred
else
# No hang
fi
2時間後にタイムアウトを設定し、この方法でjavaScriptThatStalls
をループで100回再起動できます
seq 100|xargs -II timeout $((2 * 60 * 60)) javaScriptThatStalls
私はこのbashスクリプト timeout.sh をAnthony Thyssen( his web )で見つけました。いいね。
プロセスがまだ実行されていない場合にエラーメッセージを出力したくないということですか?次に、stderr
をリダイレクトするだけです:kill $pid 2>/dev/null
。
プロセスがまだ実行されているかどうかを確認することもできます。
if ps -p $pid >/dev/null; then kill $pid; fi