GNU/Linux >> Znalost Linux >  >> Linux

Zablokovat/zabránit příkazu, pokud byl proveden během posledních X sekund/minut?

(Jen pro dokončení:příběh; nemusíte to číst, pokud nechcete vědět, proč se ptám na tuto otázku :Dostal jsem démonickou aplikaci webové kamery (nazývanou „pohyb“) s detekcí pohybu kamery. Tento démon je schopen spustit vlastní příkaz, když kamera zaznamená pohyb. Dále jsem nainstaloval malý program příkazového řádku, který může snadno odesílat oznámení push do mého mobilu s Androidem. Nakonfiguroval jsem cam-démon tak, aby spustil příkaz push-message-command, když detekuje pohyb.)

Problém:Démon spouští tento vlastní příkaz s každým snímkem, který zabere pro pohyb, což mě vede k obrovskému množství oznámení push, když dojde k nepřetržitému pohybu po dobu pouhých – řekněme – 5 sekund (snímací frekvence kamery je nastavena na 10 obrázky/sekundu, takže každou sekundu dostávám 10 push-msgs, které jsou považovány za pohyb).

Potřebuji skript nebo program, který zablokuje příkaz push-msg, pokud již byl spuštěn za posledních x sekund / minut.

Dovedl bych si představit něco jako:

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

Nemohl jsem najít snadný / přesto elegantní způsob, jak to vyřešit (bez zápisu souborů s časovými razítky a následné kontroly obsahu těchto souborů). Ani jsem nenašel někoho, kdo by měl podobný problém.

Existuje nějaký druh příkazového proxy nebo něco, co by co nejsnáze vyřešilo můj problém, jak je popsáno výše?

Přijatá odpověď:

Uložení času posledního vyvolání jako času poslední úpravy souboru

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;

Použije se jako:

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

Zaznamenává čas posledního spuštění jako čas poslední úpravy /some/file a nespustí příkaz, pokud je stáří tohoto souboru nižší než zadaná doba.

shell

S BSD nebo GNU find , můžete to udělat pomocí:

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

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

Spustit jako:

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

V každém případě budete muset uložit informace o posledním běhu na nějaké místo, které přetrvává pro další běhy. Souborový systém je pro to jasným místem. To je místo, kde si můžete zarezervovat určitou oblast pro sebe.

proces spánku s konkrétním názvem

Dalším jmenným prostorem mohou být například názvy procesů:

#! /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 "[email protected]"

K použití jako:

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

(za předpokladu sleep implementace, která se nestará o svůj argv[0] ).

Používáme bash místo sh pro jeho exec -a arg0 . Pokud nemáte bash , další podporované shelly zahrnují ksh93 , mksh , yash a zsh . Nebo se můžete vrátit k perl znovu.

Související:Povolení modulu Active Directory pro PowerShell pomocí příkazového řádku?

Všimněte si, že tento jmenný prostor není rezervován. Nic nebrání jinému uživateli vytvořit proces se stejným názvem (na rozdíl od použití ~/.lastrun soubor v přístupu založeném na souborech), nicméně vzhledem k tomu, že zde jsou všechny tyto skripty spuštěny stejným motion procesu, můžete omezit hledání procesu na procesy se stejným ID nadřazeného procesu:

Vylepšení, kdy jsou všechny skripty vždy spouštěny stejným procesem

#! /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 "[email protected]"

Pouze Linux:použijte klíč jádra s časovým limitem

V systému Linux můžete také použít klíč na svazku klíčů relace uživatele. To ve skutečnosti nebylo na to navrženo, ale tady se to hodí, protože tyto klávesy přetrvávají v průběhu času a lze jim udělit časový limit:

#! /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 "[email protected]"

Nyní na tom ve vašem případě opravdu nezáleží, protože nespouštíte dvě instance tohoto skriptu současně, ale všechny mají podmínky závodu, což nezaručuje, že dvě instance nebudou běžet ve stanoveném čase. Pokud jsou spuštěny dvě instance současně, mohou obě ověřit, že je podmínka v pořádku, než ji kterákoli z nich resetuje.

Zamykání souboru, aby se předešlo sporu

Přístup, který by to fungoval, by byl sleep proces hold lock na souboru:

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

(navíc zde oba sleep a spuštěný příkaz by podržel zámek, což by zajistilo, že se nespustí dvě instance příkazu současně, i když jejich spuštění trvá déle než sleep příkaz).


Linux
  1. $_ vs! $. Poslední argument předchozího příkazu a přesměrování výstupu?

  2. Jak zjistit, zda byl VT-X zapnutý v BIOSu?

  3. Významy sloupců v posledním příkazu

  1. 2 způsoby, jak znovu spustit poslední provedené příkazy v Linuxu

  2. Linuxový terminálový trik:Hackněte příkaz cd, abyste si zapamatovali, kde jste byli

  3. Jak určit nejlepší velikost bajtu pro příkaz dd

  1. Bash Echo Příkazový řádek spuštěn na samotném příkazovém řádku (ne ve skriptu)?

  2. Linux – Jak zobrazit příkazový řádek procesů provedených za posledních 10 sekund?

  3. Jak získat přístup k poslednímu argumentu komentovaného příkazu?