¿Cuál es la diferencia entre Ctrl-Z y kill -STOP?

14

Cuando ejecuto un comando ( makeen un proyecto grande) desde el shell, puedo escribir Ctrl-Z para detener el proceso y volver al shell. Posteriormente, puedo ejecutar fgpara continuar el proceso.

Estoy tratando de escribir un script de shell para automatizar esto (específicamente, para verificar la temperatura de mi CPU cada pocos segundos y detener el proceso si hace demasiado calor, ya que mi computadora es propensa a sobrecalentarse). Mi primer intento funcionó así (simplificado):

make &
subpid="$!"

sleep 2
# If the CPU temperature is too high...
kill -STOP "$subpid"

sleep 2
# If the CPU temperature has dropped to safe levels...
kill -CONT "$subpid"

wait "$subpid"

Lamentablemente, esto no funcionó; el envío de SIGSTOP al proceso no lo detuvo (como lo demuestra su continuo envío de salida al terminal). Corrí make &en la línea de comando, envié SIGSTOP y verifiqué el estado del proceso con ps; estaba en la lista como detenido (y comenzó de nuevo cuando envié SIGCONT), ¡pero todavía estaba arrojando resultados y elevando mi temperatura central! Detenerlo con Ctrl-Z nunca tuvo este problema, pero no sé cómo hacerlo en un script.

¿Qué hace diferente a Ctrl-Z kill -STOPy cómo puedo obtener el comportamiento del primero en un script de shell?

Taymon
fuente
Y sí, makese está ejecutando recursivamente. De hecho, creo que va varios niveles de profundidad.
Taymon

Respuestas:

12

¿Qué hace diferente a Ctrl-Z kill -STOPy cómo puedo obtener el comportamiento del primero en un script de shell?

CTRL-Zgeneralmente envía SIGTSTP (que puede bloquearse) y, aparte de otras cosas, los shells a menudo restablecen tty a un estado previamente guardado en estas ocasiones. Sin embargo, lo que es más importante, el grupo de proceso de terminal de control se establece en el PID del shell (y luego nuevamente en un PID de un trabajo reanudado con fg).

Volviendo a su problema original: el uso de una escala de frecuencia dependiente de la temperatura como, por ejemplo, Cpufreqd podría ser un mejor martillo para su uña.

Peterph
fuente
4

No quieres detener el makeproceso; desea detener el makeproceso y todos sus procesos secundarios. Apuesto a que make se ejecutaba recursivamente.

Podrías intentar set -m, luego usar en %1lugar de "$subpid".

El set -mpermite que "el control de trabajos", que está fuera de las secuencias de comandos en el interior por defecto. Creo que debería funcionar para su caso de uso, aunque la gente parece pensar que es una mala idea en general .

sourcejedi
fuente
4

Puede enviar una señal a todos los procesos en un grupo de procesos si especifica un valor PID negativo: PGID de un líder de sesión.

kill -STOP -"$subpid"

Nota: Para ejecutar un programa en una nueva sesión, use setsid make. Pero en su caso, creo que no es necesario. Sin embargo, si make se ejecuta de forma recursiva, cada instancia de make podría ser su propio líder (no estoy seguro de eso).

Otra opción podría ser usar killall:

killall -STOP make

La diferencia entre Ctrl + Z y kill -STOP:

  • Ctrl-Z en realidad envía TSTP, que puede bloquearse.
  • STOP no se puede bloquear.
Jurij
fuente
El enfoque pgid no funcionó, y produjo la siguiente línea de salida: /usr/local/bin/myscript: line 38: kill: (-10202) - No such process. Los procesos en segundo plano continuaron ejecutándose. No creo que el killallenfoque funcione porque algunos de los subprocesos parecen serlo en shlugar de hacerlo make.
Taymon
Parece que el proceso al que está enviando la señal ya ha finalizado. Los subprocesos denominados sh se generan por make. En su caso de marca y muchos subprocesos, lo mejor probablemente sería obtener los PID de todos los niños y DETENERlos a todos.
Jurij
Terminó funcionando cuando lo hice manualmente desde el shell, pero no en un script de shell. Estoy pensando que esto se debe a que cuando lo hice manualmente, el PID raíz (del que los demás heredaron su PGID) era el del primer makecomando, pero cuando lo hice desde el script, el PID raíz era del script de shell. .
Taymon
1

Ctrl+ Cse usa para matar un proceso con señal SIGINT, en otras palabras, es una muerte educada .

Ctrl+ Z se utiliza para suspender un proceso enviándole la señal SIGSTP , que es como una señal de suspensión, que se puede deshacer y el proceso se puede reanudar nuevamente.

Sin embargo, cuando se suspende un proceso, podemos reanudarlo nuevamente fg (reanudar en primer plano) y bg (reanudar en segundo plano) , pero no puedo reanudar un proceso finalizado, esa es una diferencia entre usar Ctrl+ Cy Ctrl+ Z.

¿Cómo ver el proceso suspendido?

Cuando tiene varios comandos suspendidos, para tenerlos en la lista, usa el jobscomando y la salida será:

[1]-  Stopped                 cat
[2]+  Stopped                 vi

¿Cómo matar un proceso suspendido en segundo plano?

Al usar el killcomando:

kill %ndonde n es el número de trabajo (el que está entre corchetes de la salida de puestos de trabajo), así que quiero matar gato: kill %1.

antzshrek
fuente