지난 x초/분 이내에 명령이 실행된 경우 명령을 차단/차단합니다.

지난 x초/분 이내에 명령이 실행된 경우 명령을 차단/차단합니다.

(완료하려면: 스토리;내가 왜 이런 질문을 했는지 알고 싶지 않다면 이 글을 읽을 필요가 없다.: 카메라 모션 감지("모션"이라고 함) 기능이 있는 웹캠 악마 앱이 있습니다. 악마는 카메라가 움직임을 감지하면 사용자 정의 명령을 실행할 수 있습니다. 또한 내 Android 휴대폰에 푸시 알림을 쉽게 보낼 수 있는 작은 명령줄 프로그램도 설치했습니다. 움직임이 감지되면 이 푸시 메시지 명령을 실행하도록 cam-demon을 구성했습니다. )

문제: 악마는 모션을 위해 촬영하는 모든 프레임에서 사용자 정의 명령을 실행하고 연속 모션이 5초(카메라 프레임 속도가 10으로 설정됨)일 때 초당 많은 푸시 알림 사진을 받습니다. 초당 10개의 푸시 메시지를 수신하며 이는 작업으로 간주됩니다.)

이 push-msg 명령이 지난 x초/분 내에 실행된 경우 이 명령을 차단하려면 스크립트나 프로그램이 필요합니다.

나는 다음과 같은 것을 상상할 수 있습니다 :

$ proxy_command.sh --block_time=10s --command==androidpush -msg "There was a motion in your flat!"

이 문제를 해결하는 간단하고 우아한 방법을 찾을 수 없습니다(타임스탬프가 있는 파일을 작성한 다음 해당 파일 내용을 확인하지 않고). 비슷한 문제가 있는 사람도 찾을 수 없습니다.

위에서 설명한 문제를 최대한 간단하게 해결할 수 있는 일종의 명령 에이전트나 무언가가 있습니까?

답변1

마지막 통화 시간을 파일의 마지막 수정 시간으로 저장

perl

#! /usr/bin/perl
# usage: cmd file seconds cmd args
$file = shift @ARGV;
$time = shift @ARGV;
$age = -M $file;
exit 3 if defined($age) && 86400 * $age < $time;
open $fh, ">>", $file ||
  die "Can't open $file: $!\n";
utime undef, undef, $fh;
exec @ARGV;

사용 방법:

that-script /some/file 10 androidpush -msg 'There was a motion in your flat!'

마지막으로 실행된 시간을 마지막 수정 시간으로 기록하며, /some/file파일이 지정된 시간보다 오래된 경우 명령이 실행되지 않습니다.

껍데기

BSD나 GNU를 사용하면 find다음과 같이 할 수 있습니다.

#! /bin/sh -
file=${1?} time=${2?}
shift 2

[ "$(find -- "$file" -prune -newermt "$time ago")" ] && exit 3
touch -- "$file"
exec "$@"

다음으로 실행:

that-script /some/file 10sec androidpush -msg 'There was a motion in your flat!'

그럼에도 불구하고 다음 실행을 위해 유지되도록 마지막 실행의 정보를 어딘가에 저장해야 합니다. 파일 시스템은 분명한 장소입니다. 자신을 위해 일부 영역을 유지할 수 있습니다.

특정 이름을 가진 수면 프로세스

또 다른 네임스페이스는 다음과 같습니다.

#! /bin/bash -
label=$0-$(logname)@${1?} time=${2?}
shift 2
pgrep -f "^$label" > /dev/null 2>&1 && exit 3
(exec -a "$label" sleep "$time") &
exec "$@"

다음과 같이 사용됩니다:

that-script motion 10 androidpush -msg 'There was a motion in your flat!'

( sleep구현이 그것에 대해 신경 쓰지 않는다고 가정 argv[0]).

bash우리는 대신에 sh그것을 사용하고 있습니다 exec -a arg0. 없는 경우 지원되는 다른 bash셸에는 ksh93, mksh및 가 포함됩니다. 아니면 다시 재개할 수 있습니다.yashzshperl

이 네임스페이스는 예약되어 있지 않습니다. 다른 사용자가 동일한 이름을 가진 프로세스를 생성하는 것을 막을 수 있는 방법은 없지만( ~/.lastrun파일 기반 접근 방식에서 파일을 사용하는 것과 반대) 이러한 스크립트가 모두 motion동일한 프로세스에 의해 시작된다는 점을 고려하면 다음을 사용하여 프로세스 검색을 제한할 수 있습니다. 동일한 상위 프로세스 ID 프로세스:

모든 스크립트가 항상 동일한 프로세스에 의해 시작되는 개선된 사례

#! /bin/bash -
label=$0-${1?} time=${2?}
shift 2
pgrep -P "$PPID" -f "^$label" > /dev/null 2>&1 && exit 3
(exec -a "$label" sleep "$time") &
exec "$@"

Linux에만 해당: 시간 제한이 있는 커널 키 사용

Linux에서는 사용자 세션 키링의 키를 사용할 수도 있습니다. 이는 실제로 이를 위해 설계된 것은 아니지만 시간이 지나도 키가 유지되고 시간 제한을 설정할 수 있으므로 여기에서는 편리합니다.

#! /bin/sh -
key=$0-${1?} time=${2?}
shift 2
keyctl search @us user "$key" > /dev/null 2>&1 && exit 3
key=$(keyctl add user "$key" x @us) || exit
keyctl timeout "$key" "$time" || exit
exec "$@"

동시에 두 개의 스크립트 인스턴스가 실행되지 않기 때문에 귀하의 경우에는 문제가 되지 않지만 이 모든 것에는 경쟁 조건이 있어 두 인스턴스가 규정된 시간 내에 실행되지 않을 것이라는 보장이 없습니다. 시간. 두 인스턴스가 동시에 실행 중인 경우 두 인스턴스 중 하나가 조건을 재설정하기 전에 조건이 정상인지 확인할 수 있습니다.

경쟁 조건을 피하기 위해 파일 잠금

이 문제를 해결하는 한 가지 방법은 sleep프로세스가 파일을 잠그도록 하는 것입니다.

#! /bin/sh -
file=${1?} time=${2?}
shift 2
{
  flock -n 3 || exit 3
  sleep "$time" 3>&3 &
  exec "$@"
} 3<> "$file"

(또한 sleep실행 중인 명령과 명령 모두 잠금을 유지하므로 명령보다 시간이 오래 걸리더라도 명령의 두 인스턴스가 동시에 실행되지 않도록 합니다 sleep.)

관련 정보