Quelle est la différence entre Ctrl-Z et kill -STOP?

14

Lorsque j'exécute une commande ( makesur un grand projet) à partir du shell, je peux taper Ctrl-Z pour arrêter le processus et revenir au shell. Par la suite, je peux courir fgpour continuer le processus.

J'essaie d'écrire un script shell pour automatiser cela (en particulier, pour vérifier la température de mon processeur toutes les quelques secondes et arrêter le processus s'il fait trop chaud, car mon ordinateur est sujet à une surchauffe). Ma première tentative a fonctionné comme ceci (simplifié):

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"

Malheureusement, cela n'a pas fonctionné; l'envoi de SIGSTOP au processus ne l'a pas interrompu (comme en témoigne le fait qu'il continue d'envoyer la sortie au terminal). J'ai couru make &sur la ligne de commande, envoyé SIGSTOP et vérifié l'état du processus avec ps; il a été répertorié comme arrêté (et a recommencé lorsque j'ai envoyé SIGCONT), mais il crachait toujours la sortie et augmentait ma température à cœur! L'arrêter avec Ctrl-Z n'a jamais eu ce problème, mais je ne sais pas comment faire cela dans un script.

Qu'est-ce qui différencie Ctrl-Z kill -STOPet comment puis-je obtenir le comportement du premier dans un script shell?

Taymon
la source
Et oui, makeest exécuté de manière récursive. En fait, je pense que cela va à plusieurs niveaux.
Taymon

Réponses:

12

Qu'est-ce qui différencie Ctrl-Z kill -STOPet comment puis-je obtenir le comportement du premier dans un script shell?

CTRL-Zenvoie généralement SIGTSTP (qui peut être bloqué), et - à part d'autres choses - les shells réinitialisent souvent tty dans un état précédemment enregistré à ces occasions. Plus important cependant, le groupe de processus du terminal de contrôle est défini sur le PID du shell (puis sur un PID d'un travail repris avec fg).

Revenons à votre problème d'origine: l'utilisation d'une mise à l'échelle de fréquence dépendante de la température comme par exemple Cpufreqd pourrait être en fait un meilleur marteau pour votre ongle.

peterph
la source
4

Vous ne voulez pas arrêter le makeprocessus; vous voulez arrêter le makeprocessus et tous ses processus enfants. Je parie que make était exécuté de manière récursive.

Vous pouvez essayer set -m, puis utiliser à la %1place de "$subpid".

Le set -mpermet le "contrôle des travaux", qui est désactivé par défaut dans les scripts. Je pense que cela devrait fonctionner pour votre cas d'utilisation, bien que les gens semblent penser que c'est une mauvaise idée en général .

sourcejedi
la source
4

Vous pouvez envoyer un signal à tous les processus d'un groupe de processus si vous spécifiez une valeur PID négative - PGID d'un chef de session.

kill -STOP -"$subpid"

Remarque: pour exécuter un programme dans une nouvelle session, utilisez setsid make. Mais dans votre cas, je pense que ce n'est pas nécessaire. Cependant, si make est exécuté récursivement, chaque instance de make pourrait être son propre leader (je n'en suis pas sûr).

Une autre option pourrait être d'utiliser killall:

killall -STOP make

La différence entre Ctrl + Z et kill -STOP:

  • Ctrl-Z envoie en fait TSTP, qui peut être bloqué.
  • STOP ne peut pas être bloqué.
Jurij
la source
L'approche PGID ne fonctionnait pas, et produit la ligne de sortie suivante: /usr/local/bin/myscript: line 38: kill: (-10202) - No such process. Les processus d'arrière-plan ont continué de s'exécuter. Je ne pense pas que l' killallapproche fonctionnerait parce que certains des sous-processus semblent l'être shplutôt que make.
Taymon
Il semble que le processus auquel vous envoyez le signal soit déjà terminé. Les sous-processus nommés sh sont générés par make. Dans votre cas de make et de nombreux sous-processus, le mieux serait probablement d'obtenir les PID de tous les enfants et de les arrêter tous.
Jurij
Il a fini par fonctionner quand je l'ai fait manuellement à partir du shell, mais pas dans un script shell. Je pense que c'est parce que quand je l'ai fait manuellement, le PID racine (dont les autres ont hérité de leur PGID) était celui de la première makecommande, mais quand je l'ai fait à partir du script, le PID racine était du script shell lui-même .
Taymon
1

Ctrl+ Cest utilisé pour tuer un processus avec un signal SIGINT, en d'autres termes, c'est un kill poli .

Ctrl+ Z est utilisé pour suspendre un processus en lui envoyant le signal SIGSTP , qui est comme un signal de veille, qui peut être annulé et le processus peut être repris à nouveau.

Cependant, lorsqu'un processus est suspendu, nous pouvons le reprendre à nouveau par fg (reprise au premier plan) et bg (reprise en arrière-plan) , mais je ne peux pas reprendre un processus interrompu, c'est une différence entre l'utilisation de Ctrl+ C& Ctrl+ Z.

Comment afficher le processus suspendu?

Lorsque vous avez plusieurs commandes suspendues, pour les avoir répertoriées, vous utilisez la jobscommande et la sortie sera:

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

Comment tuer un processus suspendu en arrière-plan?

En utilisant la killcommande:

kill %nn est le nombre d'emplois (celui entre crochets de la sortie de l' emploi), donc je veux tuer le chat: kill %1.

antzshrek
la source