2009-04-03 13 views
5

Queremos construir un script que se ejecute todas las noches (mata y reinicia un proceso java). Para eso necesitamos capturar el número del proceso (ya que podría haber más de un proceso en ejecución). El siguiente comando es básicamente lo que usaremos para obtener el número de procesos, probablemente con una expresión regular al final de grep. A menos que surjan mejores sugerencias.Cómo capturar el resultado de una llamada al sistema en una variable de shell?

root#ps -e |grep 'java' 
18179 pts/0 00:00:43 java 

Queremos saber cómo analizar el resultado anterior y ponerlo en una variable de entorno para que podamos usar el comando kill de la siguiente manera.

kill -9 ${processid} 
wait 10 

Nota 1: La razón por la que no podemos confiar en la orden de parada normal del servicio se debe a los procesos a veces no quieren morir. Y tenemos que usar el comando kill manualmente.

+0

¿Qué hay de pkill? –

Respuesta

4

Hay un par de opciones para resolver esto. Si usa bash, entonces la variable de shell '$!' contendrá el PID del último proceso secundario bifurcado. Así, después de haber iniciado el programa Java, hacer algo como:

echo $! > /var/run/my-process.pid 

Entonces, después de su guión de inicio se detiene el proceso de Java:

# Get the pidfile. 
pid=$(cat /var/run/my-process.pid) 

# Wait ten seconds to stop our process. 
for count in $(1 2 3 4 5 6 7 8 9 10); do 
    sleep 1 
    cat "/proc/$pid/cmdline" 2>/dev/null | grep -q java 
    test $? -ne 0 && pid="" && break 
done 

# If we haven't stopped, kill the process. 
if [ ! -z "$pid" ]; then 
    echo "Not stopping; terminating with extreme prejudice." 
    kill -9 $pid 
fi 

Asegúrese de eliminar el pidfile cuando haya terminado.

+1

"Prejucide"? ¿Es eso una broma o un error tipográfico? –

+0

Eso es lo que sucede cuando publico una respuesta antes del café de la mañana. –

+0

Además, si tiene el comando 'seq', puede hacer 'seq 1 10' en lugar del conteo manual. Sin embargo, no siempre está disponible en todos los sabores de Linux. –

0

matándolo:

ps -e | grep java | cut -f1 -d' ' | xargs kill -9 

almacenar en la variable PID:

export JAVAPID=`ps -e | grep 'java' | cut -f1 -d' '` 

comprobar que funcionaba:

echo $JAVAPID 
3
ps aux | grep java | awk '{print $1}' | xargs kill -9 

He aquí una explicación:

ps aux le da una lista de todos los procesos

grep java que todos los procesos cuyos nombres y los argumentos de línea de comandos contienen la cadena "java"

da awk '{print $1}' analiza la salida del comando grep en columnas por espacios en blanco y vuelve a imprimir solo la primera columna

xargs kill -9 pasa cada uno de los resultados del comando awk como parámetros a un comando kill -9

+2

Omita el grep: ps aux | awk '/ java/{print $ 1}' :) – andri

+0

Gracias por el consejo; No sé lo suficientemente bien como para haber sabido cómo hacer eso. Dejaré mi respuesta tal como está, porque para mí es más fácil de entender, pero me alegra que hayas hecho esa sugerencia. –

+1

¿No debería tener un grep -v grep para evitar que recopile pid de grep (ya que su línea de comando contiene la palabra java)? –

1

Usted puede conseguir fácilmente el PID o una lista de PIDs en una variable utilizando acentos abiertos y corte (o si se prefiere awk) para recuperar sólo el campo PID:

[[email protected] ~]$ ps -e | grep java | cut -d' ' -f1 
12812 
12870 
13008 
13042 
13060 

Nota en el ejemplo anterior tengo varios procesos Java que se ejecutan por lo tanto, los múltiples valores.Si guarda esto en una variable de este modo:

JAVA_PROCS=`ps -e | grep java | cut -d' ' -f1` 

Se puede recorrer los procesos de matarlos si lo desea:

for proc in $JAVA_PROCS; do 
    kill -9 $proc; 
done 

Por supuesto, si sólo está recuperando un proceso, entonces hay no hay necesidad de iterar y sólo puede funcionar como:

kill -9 $JAVA_PROCS 
1

Si haces lo que sugiere, que puede terminar la captura de la misma grep y matando que (ya que el comando grep contiene la cadena de java que te ar e buscando). Puede solucionar esto mediante la exclusión de grep (grep utilizando otro!):

pid=`ps -e | fgrep java | fgrep -v grep | awk '{print $1}'` 
# check pid has a value 
# kill $pid 

También te ps -e -opid,args.

Una mejor alternativa es usar pgrep(1) o pkill(1) si su sistema los tiene. No hay más tubos, seds, awks, cortes, xargs:

pkill -9 java 
+0

Casi publico lo mismo, pero ps -e no enumera los argumentos de cmd (al menos en mi cuadro) por lo que no hay peligro de capturar accidentalmente el comando 'grep java' en la salida de grep. – Jay

+0

Spot on, Jay, al menos para Linux. Todavía prefiero pkill, pero parece que soy una minoría. –

+0

También puede colocar paréntesis alrededor del primer carácter en grep, como en grep [j] ava grep lo ve como una expresión regular y busca una j, pero la línea de comando no coincidirá con el patrón. :) Me hace sentir sucio cuando lo hago, pero funciona bien ... – dannysauer

0

que usar algo como esto:

kill $(ps -A | grep java | cut -b 1-5) 
2

Comprendo que esto es viejo, pero ¿qué pasa:

pidof java | xargs kill 
Cuestiones relacionadas