GNU/Linux >> Tutoriales Linux >  >> Linux

¿Bloquear/prevenir el comando si se ha ejecutado en los últimos X segundos/minutos?

(Solo para completar:la historia; no es necesario que lea esto si no quiere saber por qué hago esta pregunta :Tengo una aplicación demoníaca de cámara web (llamada "movimiento") con detección de movimiento de cámara. Este demonio puede activar un comando personalizado cuando la cámara detecta un movimiento. Además, instalé un pequeño programa de línea de comandos que puede enviar fácilmente notificaciones automáticas a mi móvil Android. Configuré el demonio de la cámara para ejecutar ese comando de mensaje de inserción cuando detecta un movimiento).

El problema:el demonio activa ese comando personalizado con cada fotograma que toma para un movimiento, lo que me lleva a una gran cantidad de notificaciones automáticas cuando hay un movimiento continuo durante solo, digamos, 5 segundos (la velocidad de fotogramas de la cámara está configurada en 10 fotos/segundo, así que recibo 10 mensajes push cada segundo que se considera un movimiento).

Necesito un script o programa que bloquee ese comando push-msg si ya se ha ejecutado en los últimos x segundos/minutos.

Podría imaginar algo como:

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

No pude encontrar una manera fácil pero elegante de resolver esto (sin escribir archivos con marcas de tiempo y luego verificar el contenido de esos archivos). Tampoco pude encontrar a alguien que tuviera un problema similar.

¿Hay algún tipo de proxy de comando o algo que pueda resolver mi problema como el descrito anteriormente de la manera más fácil posible?

Respuesta aceptada:

Almacenamiento de la hora de la última invocación como hora de la última modificación de un archivo

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;

Para ser usado como:

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

Registra la hora de la última ejecución como la hora de la última modificación de /some/file y no ejecuta el comando si la antigüedad de ese archivo es inferior al tiempo especificado.

cáscara

Con BSD o GNU find , podrías hacerlo con:

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

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

Para ejecutar como:

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

En cualquier caso, deberá almacenar la información sobre la última ejecución en algún lugar que persista para las próximas ejecuciones. El sistema de archivos es un lugar obvio para eso. Ese es uno en el que puedes reservar un área para ti.

proceso de suspensión con nombre específico

Otro espacio de nombres podría ser, por ejemplo, nombres de procesos:

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

Para ser utilizado como:

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

(asumiendo un sleep implementación a la que no le importa su argv[0] ).

Estamos usando bash en lugar de sh para su exec -a arg0 . Si no tienes bash , otros shells compatibles incluyen ksh93 , mksh , yash y zsh . O podría volver a perl de nuevo.

Relacionado:¿Habilitar el módulo de Active Directory para PowerShell a través de la línea de comandos?

Tenga en cuenta que ese espacio de nombres no está reservado. No hay nada que impida que otro usuario cree un proceso con el mismo nombre (a diferencia de usar un ~/.lastrun file en el enfoque basado en archivos), sin embargo, dado que aquí todos esos scripts se inician con el mismo motion proceso, puede restringir la búsqueda de proceso a aquellos con la misma identificación de proceso principal:

Mejora para cuando todos los scripts siempre se inician con el mismo proceso

#! /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:use una clave de kernel con un tiempo de espera

En Linux, también podría usar una clave en el conjunto de claves de la sesión del usuario. Realmente no se ha diseñado para eso, pero aquí es útil ya que esas claves persisten a lo largo del tiempo y se les puede dar un tiempo de espera:

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

Ahora, realmente no importa en su caso, ya que no está ejecutando dos instancias de ese script al mismo tiempo, pero todos tienen condiciones de carrera que hacen que no garantice que dos instancias no serán ejecutar dentro del tiempo especificado. Si se ejecutan dos instancias al mismo tiempo, ambas podrían verificar que la condición es correcta antes de que cualquiera de ellas la restablezca.

Bloquear un archivo para evitar la condición de carrera

Un enfoque que funcionaría sería tener el sleep proceso mantener un bloqueo en un archivo:

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

(además aquí, ambos sleep y el comando que se está ejecutando mantendría el bloqueo, lo que garantizaría que no se ejecuten dos instancias del comando al mismo tiempo, incluso si tardan más en ejecutarse que sleep comando).


Linux
  1. Bash Echo ¿La línea de comando se ejecutó en la propia línea de comando (no en un script)?

  2. ¿Cómo acceder al último argumento de un comando comentado?

  3. ¿Hay alguna manera de encontrar el tiempo de ejecución del último comando ejecutado en el shell?

  4. ¿Cómo almacenar el resultado de un comando de shell ejecutado en una variable en python?

  5. ¿Qué podría causar que el comando de archivo en Linux informe un archivo de texto como datos binarios?

2 formas de volver a ejecutar los últimos comandos ejecutados en Linux

Cómo saber cuánto tiempo ha estado ejecutándose un proceso en Linux

Tutorial sobre el uso del último comando en la terminal de Linux

¿Cómo detectar si VT-X se ha encendido en el BIOS?

¿Cómo imprimir la última línea de un archivo comprimido gz en la línea de comando?

Comando para forzar el movimiento del brazo del disco duro a una posición específica en el plato