Hacks de terminación del proceso Bash

Contenidos

Bash Shell

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.

Procesos raíz en Linux

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

Un proceso simple matar en Linux

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

Terminación de procesos más bien definida en Linux

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

Excluir procesos propios de un comando de terminación de procesos

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 "{}"

Una versión más segura o un comando de terminación multiproceso

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'

Ejemplo de una excitación de comando de killall

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!

Suscribite a nuestro Newsletter

No te enviaremos correo SPAM. Lo odiamos tanto como tú.