GNU/Linux >> Linux Esercitazione >  >> Linux

Blocca/previeni il comando se è stato eseguito negli ultimi X secondi/minuti?

(Solo per completare:la storia; non c'è bisogno di leggere questo se non vuoi sapere perché sto facendo questa domanda :Ho ricevuto un'applicazione demone della webcam (chiamata "movimento") con rilevamento del movimento della fotocamera. Questo demone è in grado di attivare un comando personalizzato quando viene rilevato un movimento dalla telecamera. Ho inoltre installato un piccolo programma da riga di comando che può inviare facilmente notifiche push al mio cellulare Android. Ho configurato la cam-demon per eseguire quel comando push-message mentre rileva un movimento.)

Il problema:il demone attiva quel comando personalizzato con ogni fotogramma che prende per un movimento, portandomi a un'enorme quantità di notifiche push quando c'è un movimento continuo per soli – diciamo – 5 secondi (il framerate della fotocamera è impostato su 10 pics/secondo quindi ottengo 10 push-msg al secondo che è considerato un movimento).

Ho bisogno di uno script o di un programma che blocchi quel comando push-msg se è già stato eseguito negli ultimi x secondi/minuti.

Potrei immaginare qualcosa come:

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

Non sono riuscito a trovare un modo semplice/ma elegante per risolvere questo problema (senza scrivere file con timestamp e quindi controllare il contenuto di quel file). Né sono riuscito a trovare qualcuno con un problema simile.

Esiste una sorta di proxy di comando o qualcosa che possa risolvere il mio problema come descritto sopra nel modo più semplice possibile?

Risposta accettata:

Memorizzazione dell'ora dell'ultima chiamata come ora dell'ultima modifica di un file

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;

Da usare come:

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

Registra l'ora dell'ultima esecuzione come ora dell'ultima modifica di /some/file e non esegue il comando se l'età di quel file è inferiore al tempo specificato.

conchiglia

Con BSD o GNU find , potresti farlo con:

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

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

Per eseguire come:

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

In ogni caso, dovrai archiviare le informazioni sull'ultima corsa in un posto che persiste per le corse successive. Il file system è un posto ovvio per questo. Questo è uno in cui puoi riservare un'area per te stesso.

processo di sospensione con nome specifico

Un altro spazio dei nomi potrebbe essere, ad esempio, i nomi dei processi:

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

Da utilizzare come:

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

(supponendo un sleep implementazione che non si preoccupa del suo argv[0] ).

Stiamo usando bash invece di sh per il suo exec -a arg0 . Se non hai bash , altre shell che supportano che includono ksh93 , mksh , yash e zsh . Oppure puoi tornare a perl di nuovo.

Correlati:Abilitazione del modulo Active Directory per PowerShell tramite riga di comando?

Nota che quello spazio dei nomi non è riservato. Non c'è niente che impedisca a un altro utente di creare un processo con lo stesso nome (invece di usare un ~/.lastrun file nell'approccio basato su file), tuttavia dato che qui quegli script sono tutti avviati dallo stesso motion processo, puoi limitare la ricerca del processo a quelli con lo stesso ID processo padre:

Miglioramento per quando tutti gli script vengono avviati sempre con lo stesso processo

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

Solo Linux:usa una chiave del kernel con un timeout

Su Linux, potresti anche usare una chiave sul portachiavi di sessione dell'utente. Non è stato progettato proprio per quello, ma qui è utile poiché quelle chiavi persistono nel tempo e possono essere concesse un timeout:

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

Ora, nel tuo caso non importa perché non stai eseguendo due istanze di quello script contemporaneamente, ma tutti hanno condizioni di gara che non garantiscono che due istanze non saranno eseguire entro il tempo specificato. Se vengono eseguite due istanze contemporaneamente, entrambe potrebbero verificare che la condizione sia OK prima che una di esse la reimposti.

Blocco di un file per evitare la race condition

Un approccio che potrebbe aggirare il problema sarebbe avere il sleep processo di blocco di un file:

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

(in aggiunta qui, entrambi sleep e il comando in esecuzione manterrebbe il blocco che assicurerebbe che due istanze del comando non vengano eseguite contemporaneamente anche se impiegano più tempo per essere eseguite rispetto al sleep comando).


Linux
  1. Trucco del terminale Linux:hackerare il comando cd per ricordare dove sei stato

  2. Bash Echo La riga di comando eseguita sulla riga di comando stessa (non in uno script)?

  3. Il comando "java" non esegue la JVM che è stata installata

  4. Utilizzando il comando passwd dall'interno di uno script di shell

  5. C'è un modo per trovare il tempo di esecuzione dell'ultimo comando eseguito nella shell?

2 modi per rieseguire gli ultimi comandi eseguiti in Linux

Come scoprire da quanto tempo è in esecuzione un processo in Linux

Tutorial sull'utilizzo dell'ultimo comando nel terminale Linux

Come rilevare se VT-X è stato attivato nel BIOS?

Come stampare l'ultima riga di un file compresso gz nella riga di comando?

Come determinare la migliore dimensione in byte per il comando dd