基本的には、lodashと同じ機能で、X期間ごとに最大1回実行されるようにコマンドをラップすることに興味があります。throttle
機能。私は基本的にこれを実行できるようにしたいです。
throttle 60 -- check-something
another-command
throttle 60 -- check-something
another-command
throttle 60 -- check-something
これらの各コマンドに対してthrottle
(成功的に)実行されてから60秒未満が経過すると、コマンドはスキップされます。check-something
このようなものはすでに存在していますか?シェルスクリプトで簡単にできますか?
ベストアンサー1
私は基本的に何も知りませんが、ラッパー機能はこれを行います。連想配列を使用してbashで1つを実装しました。
declare -A _throttled=()
throttle() {
if [ "$#" -lt 2 ]
then
printf '%s\n' "Usage: throttle timeout command [arg ... ]" >&2
return 1
fi
local t=$1
shift
if [ -n "${_throttled["$1"]}" ]
then
if [ "$(date +%s)" -ge "${_throttled["$1"]}" ]
then
"$@" && _throttled["$1"]=$((t + $(date +%s)))
else
: printf '%s\n' "Timeout for: $1 has not yet been reached" >&2
fi
else
"$@" && _throttled["$1"]=$((t + $(date +%s)))
fi
}
基本ロジックは次のとおりです。コマンドに配列に項目がある場合は、配列値と_throttle
比較して現在の時刻を確認し、タイムアウトが期限切れになった場合はコマンドを実行し(コマンドが成功した場合)、新しいタイムアウト値を設定します。タイムアウトが期限切れになっていない場合は、情報メッセージを印刷しないでください。一方、コマンドがまだ配列にエントリがない場合は、コマンドが実行され(コマンドが成功した場合)、新しいタイムアウト値が設定されます。
ラッパー関数は引数によってコマンドを区別しないので、throttle 30 ls
同じではありません。これは、配列参照と割り当てをthrottle 30 ls /tmp
置き換えることで"$1"
簡単に変更できます"$@"
。
--
また、サンプル構文からこれを削除しました。
さらに、これは第2の解像度に限定される。
Bash バージョン 4.2 以降では、組み込みdate
関数を使用して外部コマンドの呼び出しを保存できます。printf
...
_throttled["$1"]=$((t + $(printf '%(%s)T\n' -1)))
...
...現在の時間を秒()(%s)
単位で明示的に表現する必要があります。-1
またはbash
バージョン5.0以降では:
_throttled["$1"]=$((t + EPOCHSECONDS))