実行が制限されるようにコマンドをラップする方法(例:X分ごとに最大1回実行)

実行が制限されるようにコマンドをラップする方法(例:X分ごとに最大1回実行)

基本的には、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))

おすすめ記事