El script Bash para contar el número de instancias de ejecución no funciona

El script Bash para contar el número de instancias de ejecución no funciona

Estoy escribiendo un script que detecta si ya hay alguna instancia ejecutándose en mi máquina Linux y muestra en pantalla la cantidad de instancias.

El contenido del script "detect_itself.sh" es:

#!/bin/sh

INSTANCES_NUMBER=`ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
echo "Number of detect_itself.sh instances running now =" $INSTANCES_NUMBER
echo "Second method:"
ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l
echo "Third method:"
echo `ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
echo "Please, press a key"
read -r key

Al ejecutar el script se muestra por pantalla:

Number of detect_itself.sh instances running now = 2
Second method:
1
Third method:
2
Please, press a key

Pero esperaba que mostrara:

Number of detect_itself.sh instances running now = 1
Second method:
1
Third method:
1
Please, press a key

No entiendo porque si ejecuto ps -ef | grep detect_itself.sh | grep -v -i grep | wc -lme devuelve el valor 1, pero si guardo este valor en una variable y lo muestro con echo me muestra 2.

Respuesta1

Esto sucede porque está ejecutando el pscomando en un subshell. Cuando ejecutas esto:

INSTANCES_NUMBER=`ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`

En realidad, eso bifurca una nueva subcapa para ejecutar ese comando. Debido a que esta bifurcación es una copia del padre, ahora hay dos detect_itself.shinstancias ejecutándose. Para ilustrar, ejecute esto:

#!/bin/sh
echo "Running the ps command directly:"
ps -ef | grep detect_itself.sh | grep -v -i grep
echo "Running the ps command in a subshell:"
echo "`ps -ef | grep detect_itself.sh | grep -v -i grep`"

Eso debería imprimir:

$ test.sh
Running the ps command directly:
terdon   25683 24478  0 14:58 pts/11   00:00:00 /bin/sh /home/terdon/scripts/detect_itself.sh
Running the ps command in a subshell:
terdon   25683 24478  0 14:58 pts/11   00:00:00 /bin/sh /home/terdon/scripts/detect_itself.sh
terdon   25688 25683  0 14:58 pts/11   00:00:00 /bin/sh /home/terdon/scripts/detect_itself.sh

¡Felizmente, hay una aplicación para eso! Este tipo de cosas es precisamente la razón por la que pgrepexisten. Así que cambia tu script a:

#!/bin/sh
instances=`pgrep -fc detect_itself.sh`
echo "Number of detect_itself.sh instances running now = $instances"
echo "Second method:"
ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l
echo "Third method (wrong):"
echo `ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`

Eso debería imprimir:

$ detect_itself.sh
Number of detect_itself.sh instances running now = 1
Second method:
1
Third method (wrong):
2

IMPORTANTE: esto no es algo seguro. Por ejemplo, si tiene un script llamado this_will_detect_itself, se contará. si tiene el archivo abierto en un editor de texto, eso también se contará. Un enfoque mucho más sólido para este tipo de cosas es utilizar un archivo de bloqueo. Algo como:

#!/bin/sh

if [[ -e /tmp/I_am_running ]]; then
    echo "Already running! Will exit."
    exit
else
    touch /tmp/I_am_running
fi
## do whatever you want to do here

## remove the lock file at the end
rm /tmp/I_am_running

O, mejor aún, considere usarlo trappara asegurarse de que el archivo se elimine incluso cuando el script falla. Los detalles dependerán de qué es exactamente lo que desea hacer y de por qué necesita detectar la instancia en ejecución.

información relacionada