기본적으로 lodash와 동일한 기능으로 X 기간마다 최대 한 번 실행되도록 명령을 래핑하는 데 관심이 있습니다.throttle
기능. 나는 기본적으로 이것을 실행할 수 있기를 원합니다.
throttle 60 -- check-something
another-command
throttle 60 -- check-something
another-command
throttle 60 -- check-something
이러한 각 명령에 대해 throttle
(성공적으로) 실행된 후 60초 미만이 경과하면 명령을 건너뜁니다. check-something
이와 같은 것이 이미 존재합니까? 쉘스크립트로 하면 쉽나요?
답변1
나는 기본적으로 아무것도 모르지만 래퍼 기능이 작업을 수행할 것입니다. 연관 배열을 사용하여 bash에서 하나를 구현했습니다.
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"
쉽게 변경할 수 있습니다 "$@"
.
--
또한 예제 구문에서 이를 제거했습니다.
또한 이는 두 번째 해상도로 제한됩니다.
Bash 버전 4.2 이상이면 내장 date
함수를 사용하여 외부 명령에 대한 호출을 저장할 수 있습니다.printf
...
_throttled["$1"]=$((t + $(printf '%(%s)T\n' -1)))
...
...현재 시간을 초( ) (%s)
단위로 명시적으로 표현 해야 합니다.-1
또는 bash
버전 5.0 이상에서는:
_throttled["$1"]=$((t + EPOCHSECONDS))
답변2
그리고 zsh
:
typeset -A last_run
zmodload zsh/datetime
throttle() {
local delay=$1; shift
# $cmd is the (minimally) quoted arguments of the command joined
# with spaces and used as the key for the `$last_run` associative array
local cmd="${(j: :)${(q+)@}}"
local now=$EPOCHREALTIME
local lr=$last_run[$cmd]
local t=$((now - lr))
if ((t < delay)); then
printf >&2 '%s was already run successfully %.3g seconds ago\n' "$cmd" "$t"
return 1
else
"$@" && last_run[$cmd]=$now
# $now being the time when the command started, replace with
# $EPOCHREALTIME if you want the time it finished.
fi
}
throttle 3.5 echo "test 1 2 3"
sleep 2
throttle 3.5 echo "test 1 2 3"
sleep 4
throttle 3.5 echo "test 1 2 3"
throttle
주어진 명령의 모든 인스턴스가 동일한 쉘 프로세스 내에서(하위 쉘이 아닌) 실행된다고 가정합니다 .