¿Cómo puede Bash script matar la versión “durmiente” de sí mismo que ya se está ejecutando?

Editar De los comentarios a continuación escribí una introducción confusa / engañosa, así que la reescribo.

Tengo un script de bash llamado ” temporizador de locking de pantalla ” que se puede hacer clic en el escritorio. Después de 30 minutos, bloquea la pantalla y el usuario debe ingresar su contraseña para desbloquearla. Sin embargo, si el usuario cambia de opinión o si desea restablecer el temporizador, debería poder volver a hacer clic en el acceso directo del escritorio y debería cancelar el trabajo en ejecución previo, que está inactivo y cuenta atrás.

He hecho un pequeño ensayo y error hasta el momento y he golpeado un obstáculo.

El fragmento de código relevante es:

pgrep tv-timer > ~/tv-timer.log PID=$$ # Current Process ID 

Utilizando cat ~/tv-timer.log :

 16382 20711 

Uno de estos es igual al “$ PID” anterior, pero el otro es una copia que se está ejecutando anteriormente y que quiero usar kill ##### .

¿Cuál es la mejor manera de averiguar cuál “$ PID” y matarlo?

La primera vez que se ejecuta el script, solo hay una entrada igual a “$ PID” que no quiero eliminar.

¡Gracias por tu ayuda!


El duplicado propuesto ( Impedir que el script duplicado se ejecute en sametime ) es un problema dentro de los procesos de Padres e Hijos . Las respuestas aceptadas son largas y complicadas que involucran scripts de envoltura y / o múltiples líneas de código.

La solución buscada aquí es una línea de código nuevo!

De hecho, la respuesta aceptada aquí se basa en un bash duplicado de OP ¡ QUE NO FUNCIONA!

Por favor, cambie la línea:

 pgrep tv-timer | grep -v $$ > ~/tv-timer2.log 

dentro de esto:

 pgrep tv-timer | grep -v ^$$$ > ~/tv-timer2.log 

De hecho, si una prosesses de temporizador de televisión tiene, digamos, PID = 26019 y $$ debería ser 6019, entonces grep producirá una cadena vacía, que no es lo que usted quiere.

Habiendo pasado muchas horas siguiendo al conejo blanco en varios universos alternos, encontré que el siguiente método es el único confiable:

 # If called a second time, kill the first version already running kill $(pgrep -f "${0##*/}" | grep -v ^$$) 

Si está interesado en probar esto, vea el código del Lock Screen Timer en Pregunte a Ubuntu en: ( Aplicación que bloqueará la pantalla después de un tiempo establecido para Ubuntu )

Fragmento de código de versión de producción (TL; DR)

El fragmento de código pertinente del progtwig lock-screen-timer es este:

 # Check if lock screen timer already running pID=$(pgrep -f "${0##*/}") # All PIDs matching lock-screen-timer name PREVIOUS=$(echo "$pID" | grep -v ^"$$") # Strip out this running copy ($$$) if [ $PREVIOUS != "" ]; then zenity --info --title="Lock screen timer already running" --text="Previous lock screen timer has been terminated." kill "$PREVIOUS" fi 

pgrep -f "${0##*/}"

Esto encuentra todas las apariciones del mismo ID de progtwig en ejecución con nombre ${0##*/} . Aunque el archivo ejecutable se llama ~/bin/lock-screen-timer se utiliza un acceso directo de escritorio para llamarlo. Puede llamarse “Temporizador de locking de pantalla” o “Temporizador de locking de pantalla” o “Recordarme el ciclo de lavado”. No puede ser codificado en el progtwig como en la pregunta original.

La lista resultante de identificadores de proceso se coloca en la variable $pID

echo "$pID" | grep -v ^"$$"

Esto toma el contenido de $pID (todas las apariciones en ejecución de lock-screen-timer , o se le ha cambiado el nombre de $pID escritorio) y canaliza la lista de identificadores de proceso al siguiente comando usando el carácter de canalización ( | ).

El siguiente comando grep -v elimina los ID de proceso que coinciden con $$ que es el ID de proceso actual en ejecución. La zanahoria ( ^ ) le dice a grep que haga coincidir toda la palabra, no la cadena de caracteres. Por ejemplo, el identificador del proceso actual puede ser 1518 y la versión anterior puede ser 11518 , 21518 o 31518 . En ese caso, solo haciendo coincidir 4 dígitos, el identificador del proceso hace esas 3 coincidencias porque 1518 está dentro de 11518 . La zanahoria coincide con las palabras así que 1518 <> 11518 . En la lista de ID de proceso, las palabras están separadas por espacios (en una variable) o nuevos caracteres de línea (cuando el comando ps -aux muestra en la pantalla).

El resultado de estos dos comandos es el ID de proceso del script de lock-screen-timer ejecutó anteriormente. El ID de proceso se coloca en la variable $PREVIOUS . Si no hubiera una ID anterior, el valor será “” (campo nulo).

if [ $PREVIOUS != "" ]; then

Esto prueba si $PREVIOUS no es igual a ( != ) Un campo nulo / vacío "" . Obviamente, solo podemos eliminar un ID de proceso que se esté ejecutando previamente si tenemos uno.

zenity --info --title="Lock screen timer already running" ...

Cuando ejecuta un acceso directo de escritorio, no puede hacer echo mensajes al usuario porque la GUI no los muestra. Terminan en /var/log/syslog y tienes que mostrarlos con cat o gedit , etc.

zenity es un pequeño y agradable progtwig para mostrar cuadros de diálogo y formularios desde bash a la GUI ( GUI gráfica de usuario), también conocido como Escritorio. El texto del mensaje continúa diciendo que el temporizador de locking de pantalla anterior ha finalizado. . Esto permite al usuario iniciar una nueva cuenta regresiva del temporizador o simplemente cancelar. En esencia, llamar a la secuencia de comandos por segunda vez y abortar es la forma de eliminar la primera secuencia de comandos que ya se está ejecutando.

kill "$PREVIOUS"

Esto simplemente elimina la versión ejecutada anteriormente, que queremos hacer, ya sea que iniciemos o no una nueva cuenta atrás del lock-screen-timer . Esto es sustancialmente diferente de la pregunta original porque hemos puesto los resultados de dos comandos crípticos en la única variable llamada $PREVIOUS .