メインスクリプトが実行中でタイムアウト内に完了しない場合は、完了したかどうかに応じてメインスクリプトで「何かを実行する」2番目の「遅いプロセス」を開始したいと思います。注:「遅いプロセス」がタイムアウトの前に完了した場合は、フルタイムアウトを待ちたくありません。
「遅いプロセス」が続き、パフォーマンスに関する統計とフォレンジックを収集できることを願っています。
使用を調べた停止するしかし、完了すると、私のスクリプトは終了します。
次の簡単な例を考えてみましょう。
メインディレクトリ
result=`timeout 3 ./slowprocess.sh`
if [ "$result" = "Complete" ]
then
echo "Cool it completed, do stuff..."
else
echo "It didn't complete, do something else..."
fi
遅いプロセス.sh
#!/bin/bash
start=`date +%s`
sleep 5
end=`date +%s`
total=`expr $end - $start`
echo $total >> /tmp/performance.log
echo "Complete"
ここではタイムアウトを使用してスクリプトが終了するため、何も起こりません/tmp/performance.log
。終わりたいのですが、3秒で終わらなくても次のステップに進みたいslowprocess.sh
です。main.sh
答え1
ksh/bash/zshを使う:
{
(./slowprocess.sh >&3 3>&-; echo "$?") |
if read -t 3 status; then
echo "Cool it completed with status $status, do stuff..."
else
echo "It didn't complete, do something else..."
fi
} 3>&1
()のために復元できるように、元のstdoutをfd 3()にコピーし、残りのサブシェルの3>&1
stdoutはパイプに移動します。slowprocess.sh
>&3
(...)
read -t 3
または使用したい場合timeout
(ここでGNUを想定timeout
):
timeout --foreground 3 sh -c './slowprocess.sh;exit'
終了するのを防ぎます(これはslowprocess.sh
シェルプロセスで最後のコマンドを実行し、最適化された実装に;exit
必要です)。sh
答え2
これはユビキタスシェルツールのみを使用するソリューションです。
sleep
これは、遅いプロセスをフォークし、バックグラウンドでwait
シェル組み込み待機に加えて、最初のプロセスが完了するのを待つと簡単に実行できます。みんな最初の作業だけでなく作業も実行する必要があります。
したがって、sleep
遅いプロセスとバックグラウンドでaを分岐し、両方ともパイプを介して状態を報告し、パイプから出る最初の状態を読み取るようにします。
fifo=$(mktemp -u) # if not on Linux, adapt to what your OS provides
mkfifo -m 600 "$fifo"
{ ./slowprocess.sh; echo z >"$fifo"; } &
sh -c 'sleep 3; echo a' >"$fifo" &
sleep_pgid=$!
read status <$fifo
case $status in
a) echo "That process is taking a long time"; read ignored <$fifo;;
z) echo "Done already"; kill -INT -$sleep_pgid;;
esac
rm "$fifo"
答え3
ブロックが発生してもslowprocess.sh
バックグラウンドで実行できるため、タイムアウト後も実行が続行される可能性があります。
のマニュアルページを参照して、後signal
から使用することもできます。timeout
main.sh
timeout
timeout
ガイドページから抜粋
`-s SIGNAL'
`--signal=SIGNAL'
Send this SIGNAL to COMMAND on timeout, rather than the default
`TERM' signal. SIGNAL may be a name like `HUP' or a number. Also
see *Note Signal specifications::.
この信号を内部でキャッチする必要がありますmain.sh
。
timeout
さまざまな種類の障害に対してもさまざまな状態が返されます。以下を活用することもできます。
Exit status:
124 if COMMAND times out
125 if `timeout' itself fails
126 if COMMAND is found but cannot be invoked
127 if COMMAND cannot be found
the exit status of COMMAND otherwise
$?
行が実行された後、変数に表示されますtimeout ...
。
答え4
以下は不要なジョブ制御出力を生成しますが、非常に単純な別の方法です。バックグラウンドプロセス "sleep nnn"を起動し、 "wait -n"を使用して最初のスリーププロセスと監視中のプロセスを待ちます。以下は、この技術のやや不器用な例です(即時通知に「set -o通知」を使用)。
$ (for I in $(seq 10); do sleep 1; echo $I ; done) & \
more> J1=$! ; \
more> sleep 5 & \
more> J2=$! ; \
more> time wait -n $J1 $J2
[1] 288160
[2] 288161
1
2
3
4
[2]+ Done sleep 5
real 0m5.006s
user 0m0.002s
sys 0m0.004s
$ 5
6
7
8
9
10
[1]+ Done ( for I in $(seq 10);
do
sleep 1; echo $I;
done )
$
$ (for I in $(seq 3); do sleep 1; echo $I ; done) & \
more> J1=$! ; \
more> sleep 5 & \
more> J2=$! ; \
more> time wait -n $J1 $J2
[1] 288256
[2] 288257
1
2
3
[1]- Done ( for I in $(seq 3);
do
sleep 1; echo $I;
done )
real 0m3.025s
user 0m0.004s
sys 0m0.015s
$ [2]+ Done sleep 5
$