2009-11-30 12 views
18

¿Cómo verifica si se está ejecutando un proceso en Mac OS X utilizando el nombre del proceso en un script de Bash?Compruebe si el proceso de Mac se está ejecutando utilizando Bash por nombre de proceso

Estoy tratando de escribir un script Bash que reiniciará un proceso si se ha detenido pero no hará nada si aún se está ejecutando.

+0

Estoy agregando "unix" a la lista de etiquetas porque realmente no hay nada específico de mac sobre esta pregunta ... (Saliendo de "mac" para que las personas específicas de mac lo encuentren también ...) –

+0

BTW, si están creando un proceso parecido a un daemon en OS X, eche un vistazo a 'launchd', el reemplazo de Apple para' cron', 'init',' inetd' et al. Tiene muchas opciones para iniciar y reiniciar procesos en varios contextos y tiempos. Vea 'man launchd',' man launchd.plist', y google para varios documentos y tutoriales. –

+0

Gracias Ned. De hecho, estoy usando Lingon como una interfaz fácil de usar para 'launchd'. –

Respuesta

25

Analizar esto:

ps aux | grep [-i] $ProcessName | wc -l 

... es probablemente su mejor apuesta. He aquí un pequeño script que hace lo que está buscando:

#!/bin/bash 
PROCESS=myapp 
number=$(ps aux | grep $PROCESS | wc -l) 

if [ $number -gt 0 ] 
    then 
     echo Running; 
fi 

EDIT: que inicialmente incluía una bandera -i a grep para que sea sensible a mayúsculas; Hice esto porque el programa de ejemplo que probé era python, que en Mac OS X se ejecuta como Python - si conoce el caso de su aplicación exactamente, el -i no es necesario.

La ventaja de este enfoque es que se adapta a su medida: en el futuro, si necesita asegurarse, por ejemplo, de que se están ejecutando cinco instancias de de su aplicación, ya está contando. La única advertencia es que si otra aplicación tiene el nombre de su programa en su línea de comando, podría aparecer: las expresiones regulares al grep resolverán ese problema, si es hábil (y se encuentra con esto).

Investigue las páginas man de Darwin para ps, grep y wc.

+16

Gracias. Esto funcionó con una excepción: tiene que ser '-gt 1' en lugar de' 0', porque el comando 'grep' del script Bash se cuenta como una de las líneas en' ps aux', al menos en mi pruebas preliminares –

+11

Me gusta agregar un 'grep -v grep' a la tubería antes del' wc'. De esta forma, el comando grep queda excluido de la cantidad de coincidencias encontradas. – Jacob

+0

¿Funciona con nombres de archivo y rutas realmente largos? ¿Especialmente si son similares al principio ?, p. Ej. my-long-filename-that-is-really-stupid-of-file-1, my-long-filename-that-is-really-stupid-of-file-2 ... Apuesto a que no, en al menos no tanto en Linux como en Mac OS X, usando los mismos argumentos para ps ... –

10

Otra forma es utilizar (¿abuso?) La opción -d del comando killall. Las opciones -d no matarán el proceso, sino que imprimirán lo que se hará. También saldrá con el estado 0 si encuentra un proceso de coincidencia, o 1 si no lo hace. Poniendo todo esto junto:

Para dar crédito en su debido momento, originalmente saqué esta técnica de un script en el instalador de iTunes.

+0

EWW. No voy a -1 porque creo que solo debería usarse para respuestas incorrectas o inapropiadas, pero guau. ¿Por qué hacer eso cuando puedes usar ps y grep? especialmente porque estoy bastante seguro de que usar ps y grep es exactamente lo que hace Killall ... –

+3

En realidad, killall es un poco más inteligente que 'ps | grep '. Si solo grep la salida de ps, puede obtener falsos positivos. Contráctido, pero digamos que su proceso se llama 'Biblioteca'. 'ps waux | grep Library 'coincidirá con muchas cosas en una Mac. El método killall, aunque un poco loco, lo admito, solo coincidirá con un proceso real llamado 'Biblioteca'. – amrox

+0

Lo siento, pero ¿qué sistema estás usando? No veo la opción -d en el comando killall. http://linux.die.net/man/1/killall – sobi3ch

0

¿Mac tiene pidof? ...

if pidof $processname >/dev/null ; then echo $processname is running ; fi 
+1

No, desafortunadamente no. – amrox

0

¡Está seguro!

pgrep, pkill y pfind para OpenBSD y Darwin (Mac OS X)

http://proctools.sourceforge.net

(también disponible a través de MacPorts: Información proctools puerto)

pidof por nightproductions.net

+0

Excelentes cosas, pero no en el estándar. A veces es mejor resolver este problema solo con el material estándar, ¡a veces no! –

2

Me falta reputación para comentar la respuesta de killall anterior, pero está killall -s por hacerlo sin enviar ninguna señal:

killall -s "$PROCESSNAME" &> /dev/null 
if [ $? -eq 0 ]; then 
    echo "$PROCESSNAME is running" 
    # if you also need the PID: 
    PID=`killall -s "$PROCESSNAME" | awk '{print $3}'` 
    echo "it's PID is $PID" 
fi 
4

Este simple comando hará el truco. Los corchetes que rodean el nombre del proceso impiden que se muestre el comando grep en la lista de procesos. Tenga en cuenta que no hay espacio después de la coma.Puede haber algunos problemas de portabilidad como ps en algunos sistemas UNIX puede requerir un guión antes de las opciones:

ps axo pid,command | grep "[S]kype" 

La ventaja es que se pueden utilizar los resultados en una sentencia if como esta:'

if [[ ! $(ps axo pid,command | grep "[i]Tunes.app") ]]; then 
    open -a iTunes 
fi 

O si lo prefiere este estilo:

[[ ! $(ps axo pid,command | grep "[S]kype") ]] && open -a Skype || echo "Skype is up" 

Otra ventaja es que se puede obtener el PID mediante la adición de una tubería a awk '{print $ 1}'.

echo "iTunes pid: $(ps axo pid,command | grep "[i]Tunes.app" | awk '{print $1}')" 
0

he extendido un guión pidof encontrado en la red para utilizar expresiones regulares (generalmente subcadenas) y ser sensible a mayúsculas

#!/bin/sh 
ps axc |awk "BEGIN{ n=tolower(\"$1\")}\ 
    tolower(\$5) ~n {print \$1}"; 

acaba de crear un script llamado "pidof" con estos contenidos, y ponerlo en ti camino, es decir, en uno de los directorios en

echo $PATH 

y hacerlo ejecutable (tal vez usando sudo)

chmod 755 /usr/local/bin/pidof 

y utilizar de esta manera, por supuesto

kill -9 `pidof pyth` 
22

Una solución más corto:

if pgrep $PROCESS_NAME; then 
    echo 'Running'; 
fi 

Explicación:

pgrep salidas con 0 si no es un proceso de correspondencia $PROCESS_NAME correr, de lo contrario, existe con 1.
if verifica el código de salida pgrep, y, en lo que respecta a los códigos de salida, 0 es correcto.

+3

Es posible que desee usar '-x', porque de forma predeterminada coincide con las subcadenas. '-x' cambia este comportamiento de tal manera que requiere una coincidencia exacta del nombre del proceso. – Auke

+0

@Hypermattt No es la respuesta aceptada porque la escribió 4 años después de que hice la pregunta. Solución fresca, sin embargo. Definitivamente tiene mi voto. –

+0

No funciona desafortunadamente si está ejecutando algo en un contenedor (por ejemplo, python). La solución de Jed Smith podría funcionar allí mejor – Evils

0

Quizás sea demasiado tarde para el OP pero esto puede ayudar a otros que encuentren este hilo.

La siguiente modificación del tema amrox anterior funciona bien para reiniciar las aplicaciones en mi OS X:

killall -d TextEdit &> /dev/null && killall TextEdit &> /dev/null; open -a TextEdit 

utilizo el siguiente AppleScript para actualizar y reiniciar los demonios:

tell application "System Events" to set pwd to POSIX path of container of (path to me) 
do shell script "launchctl unload -w /Library/LaunchDaemons/time-test.plist; cp -f " & quoted form of pwd & "/time-test.plist /Library/LaunchDaemons; launchctl load -w /Library/LaunchDaemons/time-test.plist" with administrator privileges 

asume la el archivo plist original o actualizado está en el mismo directorio que el AppleScript.

3

Puede usar killall o kill, dependiendo de si está tratando de encontrar la tarea por PID o por su nombre.

Por Nombre:

if ! killall -s -0 $PROCESS_NAME >/dev/null 2>&1; then 
    # Restart failed app, or do whatever you need to prepare for starting the app. 
else 
    at -f $0 +30seconds # If you don't have this on cron, you can use /usr/bin/at 
fi 

Por PID:

if ! kill -0 $PID 2>/dev/null; then 
    # Restart app, do the needful. 
else 
    at -f $0 +30seconds 
fi 

Si nos fijamos en el Manual OSX verá un conjunto diferente de los comandos de gestión de procesos; dado que no es el kernel de Linux, tiene sentido que administren los procesos de manera diferente.

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/killall.1.html

Un ejemplo del resultado de mi terminal (ponchando el usuario y el nombre de host, por supuesto):

[email protected]:~$ kill -0 782 # This was my old, stale SSH Agent. 
bash: kill: (782) - No such process 
[email protected]:~$ echo $? 
1 

[email protected]:~$ kill -0 813 # This is my new SSH agent, I only just created. 
[email protected]:~$ echo $? 
0 

El código de retorno de una matanza -0 siempre resultará en una forma segura de compruebe si el proceso se está ejecutando, porque -0 no envía ninguna señal que pueda ser manejada por una aplicación. No matará a la aplicación, y "matar" solo se llama "matar" porque generalmente se usa para detener una aplicación.

Cuando observa las interfaces que utiliza en la fuente, verá que en realidad está interactuando con la tabla de proceso directamente (y no almacenando una salida potencialmente cargada de ps) y simplemente enviando una señal a una aplicación. Algunas señales indican que la aplicación se debe apagar o detener, mientras que otras señales indican que debe reiniciar los servicios o volver a leer la configuración o volver a abrir los descriptores de archivos para registrar los archivos que se han girado recientemente. Hay una gran cantidad de cosas que "kill" y "killall" pueden hacer que no terminan la aplicación, y se usan regularmente para enviar una señal a la aplicación.

Cuestiones relacionadas