私はbashスクリプトに不慣れで、いくつかのサンプルスクリプトから始めました。
1つは次のとおりです。
#!/bin/bash
SECONDS=5
i=1
while true
do
echo "`date`: Loop $i"
i=$(( $i+1 ))
sleep $SECONDS
done
これは次の結果になります:
Sunday 10 May 15:08:20 AEST 2020: Loop 1
Sunday 10 May 15:08:25 AEST 2020: Loop 2
Sunday 10 May 15:08:35 AEST 2020: Loop 3
Sunday 10 May 15:08:55 AEST 2020: Loop 4
...そして、私がスクリプトに期待していたことや望んでいたことではありません。
ループを実行するたびに、秒が2倍になるのはなぜですか
bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
SECONDS
はbashの内部変数だからです。シェルが実行されていた時間を格納します。
man bash
:
秒
このパラメーターが参照されるたびに、シェルの呼び出しからの秒数が返されます。値がSECONDSに割り当てられている場合、以降の参照で返される値は、割り当てからの秒数と割り当てられた値です。
したがって、スクリプトは次のように機能します。
この構成には2次の問題があります。ループ内の処理にかなりの時間がかかる場合(たとえば1.4秒)、ループは6.4秒ごとにしか繰り返されません。
それが重要な場合は、代わりにループをカウントできます。
#!/bin/bash
Expired=$(( SECONDS + 23 ))
Tick=5
Iter=1
while (( SECONDS < Expired )); do
echo "$(date '+%T.%N'): Loop $Iter"
sleep 1.4 #.. Simulate work.
echo "$(date '+%T.%N'): Idle"
sleep $(( Iter++ * Tick - SECONDS ))
done
ループ時間は、SECONDSの整数精度内で安定しています。
Expiredを初期化するために、より複雑な計算を実行できます(たとえば、2つの日付コマンドを使用して、真夜中の前の秒を検索します)。