Al desarrollar código Bash de múltiples subprocesos, administrar procesos de servidor o crear controles de procesos, uno de los principales desafíos suele ser terminar de manera correcta, eficiente y precisa los procesos Bash existentes. Este post le mostrará cómo.
Que es un Procedimiento Bash?
Un procedimiento Bash es simplemente un ejecutable que se está ejecutando. A modo de ejemplo, cuando inicia la calculadora en su entorno de escritorio, se crea un procedimiento Bash. Tal bash tiene dos identificadores de procedimiento principales, a saber, el PID y el PPID, los Identificador de procedimiento, y el Identificador de procedimiento principal.
En resumen, el PID contiene un ID único basado en un número para una aplicación en ejecución determinada (dicho de otra forma, un procedimiento), mientras que el PPID para cualquier aplicación en ejecución dada (dicho de otra forma, procedimiento) almacena el PID padre del procedimiento que inició esta nueva aplicación, de ahí el término ‘Padre’.
Además puede ver inmediatamente cómo esto forma una estructura en forma de árbol, entrelazando todos los procesos hasta la raíz / primer procedimiento que tiene un PPID de 0.
Para obtener un post relacionado que proporciona información adicional y un ejemplo práctico de PID y PPID, es factible que desee revisar nuestro post Exportación de variables en Bash: el por qué y el cómo.
La administración del procedimiento de Bash parece fácil a primera vista (simplemente ejecute ps -ef
en la línea de comandos de su terminal para ver todos los procesos que se ejecutan en su sistema, con el prefijo PID y PPID identificadores.
Inclusive terminar un procedimiento parece fácil, pero pronto comienzan a aparecer advertencias y trampas cuando maneja sistemas de administración de procesos más complejos.
Terminar un procedimiento de Bash
Comencemos de manera simple comenzando el gnome-calculator
en la línea de comando y posteriormente terminando el procedimiento.
gnome-calculator & ps -ef | grep gnome-calculator kill -9 $RELEVANT_PID
Empezamos gnome-calculator
en modo de fondo (usando &
al final del comando), de modo que podamos tener nuestro indicador de terminal de vuelta inmediatamente sin tener que iniciar otra sesión de terminal.
A continuación, usamos ps -ef
en combinación con una pipa|
) y el grep
comando para localizar el ID del procedimiento (PID) de nuestra calculadora. A continuación, lo terminamos con una señal 9 kill
mando. Reemplazar $RELEVANT_PID
en el código con el PID informado por ps
si prueba este código.
Tenga en cuenta que el procedimiento en segundo plano finaliza inmediatamente kill -9
instrucción. A pesar de esto, el símbolo del sistema de Bash regresa tan rápido que vuelve inclusive antes de que el programador de procesos pueda informar que el procedimiento en segundo plano finalizó.
Y solo lo hará cuando esa notificación esté en línea con el trabajo existente, dicho de otra forma, está más basada en extracción que en inserción. Cuando pulsamos enter, el sistema verifica y nos notifica que el primer procedimiento en segundo plano ha terminado, o más bien fue terminado / eliminado; [1]+ Killed gnome-calculator
.
Volviendo a nuestro kill command
, una señal 9 kill
es una de las muertes más destructivas que existen. Simplemente, termina el programa en el acto sin ser amable al respecto. Puede revisar la sección ‘Numeración de señales para señales estándar’ alcanzable desde el man signal.7
comando ejecutado en el símbolo del sistema de su terminal para obtener una lista de todas las señales disponibles y sus números coincidentes.
Para los propósitos de este post, usaremos señal 9 para terminar siempre de manera inmediata y efectiva un procedimiento. A pesar de esto, inclusive cuando se utiliza un señal 9 matar / terminar el procedimiento, a veces un procedimiento puede permanecer en un difunto estado.
No sucede a menudo en el trabajo general de DevOps, y si lo hace, de forma general significa que hubo algunos problemas serios en el código del programa (el procedimiento que se está ejecutando) para comenzar, o con el hardware del sistema o el sistema operativo.
Evitar errores y elegir procesos propios
Comenzando de nuevo con el procedimiento anterior, ¿hay alguna manera de automatizar la PID selección para que no necesitemos escribir manualmente, y para que podamos usarlo desde un script? Seguro que lo hay;
gnome-calculator & ps -ef | grep 'gnome-calculator' | grep -v 'grep' | awk '{print $2}' ps -ef | grep 'gnome-calculator' | grep -v 'grep' | awk '{print $2}' | xargs kill -9
Aquí empezamos de nuevo nuestro gnome-calculator
en modo de fondo, y nuevamente usado ps
y grep
para hallar nuestro procedimiento. Ahí es donde termina la similitud. En la próxima instrucción dentro del conjunto de tuberías Bash (pasando información del comando anterior al siguiente usando un símbolo de tubería: |
) excluimos el grep
procedimiento en sí (además enumerado como parte del ps
salida puesto que se ejecuta durante nuestra secuencia de comando y, por eso, es auto-recogido por el grep
), usando el -v
opción a grep
y excluyendo la palabra 'grep'
.
Para terminar, imprimimos el PID (ID de procedimiento) de cualquier procedimiento descubierto usando awk
e imprimiendo el segundo ($2
) columna de la salida solamente. Vemos que solo una PID se devuelve, lo que coincide con el hecho de que solo tenemos un gnome-calculator
empezado.
Nuestro comando final agrega un xargs
comando con un kill -9
instrucción para terminar nuestro (s) procedimiento (s). xargs funciona de manera semejante a una tubería en sí, pero es más capaz de manejar información de entrada y pasarla correctamente, permitiendo ciertos programas como kill
(que no puede comprender de forma nativa cuando es simple PIDse le envían) para aceptar entradas directas, o más bien opciones, como el ID de procedimiento que se transmite aquí. Tenga en cuenta que xargs tiene el prefijo de una tubería.
Nuestra inclusión de un grep -v 'grep'
evita no solo el error de la eventual kill
comando no poder hallar el PID asociado con el original grep
comando (puesto que desde entonces ha terminado, habiendo cumplido su deber de grepping para el 'gnome-calculator'
texto), en segundo lugar, además evita el riesgo de finalizar otro comando / procedimiento más nuevo que puede haberse iniciado desde el original. grep
terminado, con el mismo ID de procedimiento! Aún cuando la oportunidad de que esto ocurra es pequeña, es factible.
Trabajar estas cosas en nuestro comando se ve mejor, pero aún no es perfecto. ¿Qué es esto es un servidor con 10 usuarios y los 10 han iniciado una calculadora? Suponiendo que tengamos privilegios similares a sudo, ¿verdaderamente queremos terminar los procesos de la calculadora de los otros usuarios? Probablemente no. Entonces, podemos ir un paso más allá y establecer nuestro comando de la próxima manera:
gnome-calculator & ps -ef | grep 'gnome-calculator' | grep -v 'grep' | grep "$(whoami)" | awk '{print $2}' ps -ef | grep 'gnome-calculator' | grep -v 'grep' | grep "$(whoami)" | awk '{print $2}' | xargs kill -9
En este ejemplo insertamos un pequeño comando adicional, a saber grep "$(whoami)"
, que ejecutó una subcapa ($(...)
) y posteriormente ejecuta whoami
dentro de esa subcapa. los whoami
El comando devolverá al terminal los usuarios registrados hoy en día. ¡Bingo! Ahora terminamos solo nuestros propios procesos.
¿Perfecto? No, por desgracia los errores aún son posibles inclusive con una línea de comando tan detallada y ajustada. A modo de ejemplo, si la lista de procesos contiene locale o caracteres impares, nuestro grep
potencialmente aún puede fallar. Tal vez la versión más segura sería algo parecido a:
gnome-calculator & ps -ef | grep -Ei --binary-files=text "^$(whoami) [0-9 ]+:.*gnome-calculator$" | grep --binary-files=text -v 'grep' | awk '{print $2}' | grep --binary-files=text -o '[0-9]+' | xargs -I{} kill -9 "{}"
En este ejemplo, definimos nuestro grep
comando mucho más restrictivo con una expresión regular: inicio (indicado por ^
) con el nombre de usuario (usando whoami
en una subcapa), seguido de un espacio obligatorio, seguido solo de los caracteres 0-9
y espacio, al menos uno o más (como lo indica +
), seguido de dos puntos obligatorios (parte del tiempo), seguido de cualquier carácter hasta el nombre de nuestro programa, que debe llenarse hasta el final de la línea (como lo indica $
). los grep
utiliza expresiones regulares extendidas (-E
) y no distingue entre mayúsculas y minúsculas (-i
opción, o simplemente i
cuando se agrega a la existente -E
opción)
Además protegemos nuestro grep por la extraña oportunidad de configuración regional o caracteres extraños usando --binary-files=text
, y escribimos nuestros xargs de una manera más segura indicando una cadena de reemplazo y citando la cadena de reemplazo.
Para terminar, insertamos un adicional grep -o
con una expresión regular que busca los números 0-9
solamente. Por eso, inclusive si algún programa intentara engañar a este procedimiento matando la línea de comando, sería más difícil hacerlo.
Como alternativa interesante a la definición de una línea de comando de análisis, es factible que además desee echar un vistazo a la killall
mando:
gnome-calculator & killall 'gnome-calculator'
Para obtener más información sobre este comando, puede entrar al manual usando man killall
. los killall
El comando además le posibilita configurar opciones como --user
para matar solo los procesos que posee el usuario especificado, etc.
Terminando
El manejo de procesos de varias maneras nos posibilita escribir scripts de vigilancia de procesos, automatizar el manejo de procesos, desarrollar mejor código bash de múltiples subprocesos, administrar procesos mejor y más. ¡Disfruta de tus nuevas habilidades de Bash!