¿Cómo encontrar el PID de Tomcat y eliminarlo en Python?
Pregunta
Normalmente, uno cierra Apache Tomcat ejecutando su shutdown.sh
script (o archivo por lotes).En algunos casos, como cuando el contenedor web de Tomcat aloja una aplicación web que hace algunas cosas locas con subprocesos múltiples, ejecuta shutdown.sh
se apaga con gracia alguno partes de Tomcat (como puedo ver, más memoria disponible regresa al sistema), pero el proceso de Tomcat continúa ejecutándose.
Estoy intentando escribir un script Python simple que:
- llamadas
shutdown.sh
- Carreras
ps -aef | grep tomcat
para encontrar cualquier proceso con Tomcat referenciado - Si corresponde, finaliza el proceso con
kill -9 <PID>
Esto es lo que tengo hasta ahora (como prototipo; por cierto, soy nuevo en Python):
#!/usr/bin/python
# Imports
import sys
import subprocess
# Load from imported module.
if __init__ == "__main__":
main()
# Main entry point.
def main():
# Shutdown Tomcat
shutdownCmd = "sh ${TOMCAT_HOME}/bin/shutdown.sh"
subprocess.call([shutdownCmd], shell=true)
# Check for PID
grepCmd = "ps -aef | grep tomcat"
grepResults = subprocess.call([grepCmd], shell=true)
if(grepResult.length > 1):
# Get PID and kill it.
pid = ???
killPidCmd = "kill -9 $pid"
subprocess.call([killPidCmd], shell=true)
# Exit.
sys.exit()
Estoy luchando con la parte media - con la obtención de la grep
resultados, comprobando si su tamaño es mayor que 1 (ya que grep
siempre devuelve una referencia a sí mismo, siempre se devolverá al menos 1 resultado, creo), y luego analiza ese PID devuelto y lo pasa al killPidCmd
.¡Gracias de antemano!
Solución
necesitas reemplazar grepResults = subprocess.call([grepCmd], shell=true)
con grepResults = subprocess.check_output([grepCmd], shell=true)
si desea guardar los resultados del comando en grepResults.Luego puedes usar split para convertir eso en una matriz y el segundo elemento de la matriz será el pid: pid = int(grepResults.split()[1])'
Sin embargo, eso sólo matará el primer proceso.No mata todos los procesos si hay más de uno abierto.Para hacer eso tendrías que escribir:
grepResults = subprocess.check_output([grepCmd], shell=true).split()
for i in range(1, len(grepResults), 9):
pid = grepResults[i]
killPidCmd = "kill -9 " + pid
subprocess.call([killPidCmd], shell=true)
Otros consejos
Puede agregar "c" a ps para que solo se imprima el comando y no los argumentos.Esto impediría que grab coincida consigo mismo.
Sin embargo, no estoy seguro de si Tomcat aparece como una aplicación Java, por lo que es posible que esto no funcione.
PD:Obtuve esto buscando en Google:"grep incluye a uno mismo" y el primer resultado tenía esa solución.
EDITAR:¡Culpa mía!¿Está bien algo como esto entonces?
p = subprocess.Popen(["ps caux | grep tomcat"], shell=True,stdout=subprocess.PIPE)
out, err = p.communicate()
out.split()[1] #<-- checkout the contents of this variable, it'll have your pid!
Básicamente, "out" tendrá la salida del programa como una cadena que puedes leer/manipular.
Crear procesos secundarios para ejecutar ps
y la cadena coincide con la salida con grep
no es necesario.Python tiene un excelente manejo de cadenas 'integrado' y Linux expone toda la información necesaria en /proc.El montaje procfs es donde las utilidades de línea de comando obtienen esta información.También podría ir directamente a la fuente.
import os
SIGTERM = 15
def pidof(image):
matching_proc_images = []
for pid in [dir for dir in os.listdir('/proc') if dir.isdigit()]:
lines = open('/proc/%s/status' % pid, 'r').readlines()
for line in lines:
if line.startswith('Name:'):
name = line.split(':', 1)[1].strip()
if name == image:
matching_proc_images.append(int(pid))
return matching_proc_images
for pid in pidof('tomcat'): os.kill(pid, SIGTERM)