2010-03-27 33 views
6

ahora esto es embarazoso. Estoy escribiendo guiones rápidos y no puedo entender por qué esta afirmación no funciona.¿Continuar script si solo se está ejecutando una instancia?

if [ $(pidof -x test.sh | wc -w) -eq 1 ]; then echo Passed; fi 

También intenté usar las contra-marcas en lugar de $() pero aún no funcionaría.

¿Puedes ver lo que está mal con él? pidof -x test.sh | wc -w devuelve 1 si lo ejecuto dentro del script, por lo que no veo ningún motivo por el que básicamente if [ 1 -eq 1 ] no pasara.

¡Muchas gracias!

+0

Funciona para mí. – pajton

+0

Es una buena práctica citar siempre expresiones en pruebas, en caso de que resulten ser la cadena vacía. En este caso, sin embargo, estoy bastante seguro de que 'wc -w' está garantizado para imprimir algo? Más vale prevenir que lamentar. – Cascabel

+0

¿Se puede repetir el eco si se comprueba qué está imprimiendo? ¿Ves si no funciona porque es cero o porque son dos? – Cascabel

Respuesta

6

Jefromi es correcto; Aquí está la lógica Creo que desee:

#!/bin/bash 
# this is "test.sh" 

if [ $(pidof -x test.sh| wc -w) -gt 2 ]; then 
    echo "More than 1" 
    exit 
fi 

echo "Only one; doing whatever..." 
+0

El problema con esto es que no va a funcionar en todas partes en su código; si coloca esto dentro de una construcción de bucle que también crea una subshell, obtendrá tres conteos. Pon eso dentro de otro ciclo, cuatro cuentas. – Cascabel

+1

Es cierto. Pero, si se supone que es una simple comprobación al comienzo de un script, del cual solo desea una instancia única que se ejecute a la vez, esto está limpio y funciona. ¿Qué sería mejor (pregunta sincera)? –

+0

Lo que escribió Kevin es en este caso una causa. ¿Pero puedes explicar por qué wc (así como también awk field count) devuelve n + 1? si I 'echo $ (pidof -x test.sh)> wc.txt' y luego' wc -w wc.txt' devuelve correctamente '1 wc.txt' – Gargauth

3

Ah, la verdadera respuesta: cuando utiliza una tubería, fuerza la creación de una subshell. Esto siempre hará que se obtiene un número aumentado:

#!/bin/bash 

echo "subshell:" 
np=$(pidof -x foo.bash | wc -w) 
echo "$np processes" # two processes 

echo "no subshell:" 
np=$(pidof -x foo.bash) 
np=$(echo $np | wc -w) 
echo "$np processes" # one process 

Sinceramente, no estoy seguro de lo que el camino más corto es hacer lo que realmente quiere. Puede evitarlo todo creando un archivo de bloqueo; de lo contrario, probablemente tenga que rastrear a través de ppid a todos los procesos de nivel superior y contarlos.

+0

Gracias por su respuesta. Jugando con su ejemplo, veo que el problema con mi script es en realidad con la parte 'wc -w' del guión y no con el desove de subshell. Devuelve n + 1, lo cual es interesante. – Gargauth

+0

@Andrew: er, 'wc -w' definitivamente cuenta correctamente. Simplemente pruebe con "echo 1352 | wc -w" y puede ver fácilmente que cuenta un pid como una palabra. – Cascabel

+0

Dado que todos los actores pueden cooperar (son instancias del mismo script), un archivo de bloqueo parece ser el camino a seguir. Me gusta * lockfile * http://linux.die.net/man/1/lockfile del paquete * procmail * http://www.procmail.org/ –

1

Si se utiliza la opción -o omitir el PID del guión ($$), entonces solamente el PID del subnivel y cualesquiera otras instancias de la secuencia de comandos (y cualquier subniveles que podrían desovar) se tendrán en cuenta, por lo que la prueba pasará cuando hay sólo una instancia:

if [ $(pidof -x -o $$ test.sh | wc -w) -eq 1 ]; then echo Passed; fi 
2

que no tiene que pasar el resultado de pidof a wc para contar cuántas hay are..use la shell

r=$(pidof -x -o $$ test.sh) 
set -- $r 
if [ "${#@}" -eq 1 ];then 
echo "passed" 
else 
echo "no" 
fi 
0

Así es como yo lo haría:

if [ "`pgrep -c someprocess`" -gt "1" ]; then 
    echo "More than one process running" 
else 
    echo "Multiple processes not running" 
fi 
0

sólo comprueban la existencia de cualquiera (o más) de los procesos identificados como test.sh, el código de retorno será 1 si no se encuentra ninguno:

pidof -x test.sh >/dev/null && echo "Passed" 
1

Si no desea utilizar un fichero de bloqueo ... puede probar esto:

#!/bin/bash 

if [[ "$(ps -N -p $$ -o comm,pid)" =~ $'\n'"${0##*/}"[[:space:]] ]]; then 
    echo "aready running!" 
    exit 1 
fi 

PS: podría necesitar un ajuste para un raro $ {0 ## * /}

Cuestiones relacionadas