Comment utiliser le contrôle des tâches de Bash pour gérer les processus de premier plan et d’arrière-plan

introduction

Dans ce guide, nous expliquerons commentbash, le système Linux et votre terminal s'unissent pour offrir un contrôle des processus et des tâches. Dans unprevious guide, nous avons discuté de la manière dont les commandesps,kill etnice peuvent être utilisées pour contrôler les processus sur votre système.

Cet article se concentrera sur la gestion des processus de premier plan et d’arrière-plan et montrera comment exploiter les fonctions de contrôle des tâches de votre shell pour gagner en souplesse dans l’exécution de commandes.

Gestion des processus de premier plan

La plupart des processus que vous démarrez sur une machine Linux seront exécutés au premier plan. La commande commencera à exécuter, bloquant l’utilisation du shell pendant toute la durée du processus. Le processus peut permettre une interaction de l'utilisateur ou peut simplement exécuter une procédure, puis se terminer. Toute sortie sera affichée par défaut dans la fenêtre du terminal. Nous allons discuter de la méthode de base pour gérer les processus de premier plan ci-dessous.

Démarrer un processus

Par défaut, les processus sont démarrés au premier plan. Tant que le programme ne sera pas quitté ou ne changera pas d’état, vous ne pourrez pas interagir avec le shell.

Certaines commandes de premier plan se ferment très rapidement et vous ramènent presque immédiatement à une invite du shell. Par exemple, cette commande:

echo "Hello World"

Cela afficherait «Hello World» sur le terminal, puis vous renverriez à votre invite de commande.

L'exécution d'autres commandes au premier plan prend plus de temps, bloquant l'accès au shell pour la durée. Cela peut être dû au fait que la commande effectue une opération plus étendue ou qu'elle est configurée pour s'exécuter jusqu'à ce qu'elle soit explicitement arrêtée ou jusqu'à ce qu'elle reçoive une autre entrée de l'utilisateur.

Une commande qui s'exécute indéfiniment est l'utilitairetop. Après le démarrage, il continuera à s'exécuter et à mettre à jour son affichage jusqu'à ce que l'utilisateur termine le processus:

top

Vous pouvez quitter en tapant «q». Certains processus n’ont pas de fonction de fermeture dédiée. Pour les arrêter, vous devrez utiliser une autre méthode.

Mettre fin à un processus

Supposons que nous démarrions une simple bouclebash sur la ligne de commande. Nous pouvons démarrer une boucle qui imprimera «Hello World» toutes les dix secondes. Cette boucle continuera toujours, jusqu'à ce qu'elle se termine explicitement:

while true; do echo "Hello World"; sleep 10; done

Les boucles n'ont pas de touche "Quitter". Nous devrons arrêter le processus en lui envoyant unsignal. Sous Linux, le noyau peut envoyer des signaux de processus afin de leur demander de quitter ou de changer d'état. Les terminaux Linux sont généralement configurés pour envoyer le signal «SIGINT» (généralement le signal numéro 2) au processus de premier plan actuel lorsque la combinaison de touchesCTRL-C est enfoncée. Le signal SIGINT indique au programme que l'utilisateur a demandé la terminaison à l'aide du clavier.

Pour arrêter la boucle que nous avons commencée, maintenez la touche Ctrl enfoncée et appuyez sur la touche «c»:

CTRL-C

La boucle se terminera, rendant le contrôle au shell.

Le signal SIGINT envoyé par la combinaisonCTRL-C est l'un des nombreux signaux pouvant être envoyés aux programmes. La plupart des signaux ne sont associés à aucune combinaison de clavier et doivent être envoyés en utilisant la commandekill à la place (nous aborderons cela plus tard).

Processus de suspension

Nous avons mentionné ci-dessus que le processus de premier plan bloquera l'accès au shell pendant toute la durée de son exécution. Que se passe-t-il si nous démarrons un processus au premier plan, mais réalisons ensuite que nous avons besoin d'un accès au terminal?

Un autre signal que nous pouvons envoyer est le signal «SIGTSTP» (typiquement le signal numéro 20). Lorsque nous frapponsCTRL-Z, notre terminal enregistre une commande «suspend», qui envoie ensuite le signal SIGTSTP au processus de premier plan. Cela interrompra fondamentalement l'exécution de la commande et renverra le contrôle au terminal.

Pour le démontrer, utilisonsping pour nous connecter à google.com toutes les 5 secondes. Nous ferons précéder la commandeping decommand, ce qui nous permettra de contourner tous les alias de shell qui définissent artificiellement un nombre maximum sur la commande:

command ping -i 5 google.com

Au lieu de terminer la commande avecCTRL-C, saisissezCTRL-Z à la place:

CTRL-Z

Vous verrez une sortie qui ressemble à ceci:

Output[1]+  Stopped                 ping -i 5 google.com

La commandeping a été temporairement arrêtée, vous donnant à nouveau accès à une invite du shell. Nous pouvons utiliser l'outil de processusps pour montrer ceci:

ps T
Output  PID TTY      STAT   TIME COMMAND
26904 pts/3    Ss     0:00 /bin/bash
29633 pts/3    T      0:00 ping -i 5 google.com
29643 pts/3    R+     0:00 ps t

Nous pouvons voir que le processusping est toujours répertorié, mais que la colonne «STAT» contient un «T». La page de manuel deps nous indique que cela représente un travail qui a été «arrêté par un signal de contrôle de travail».

Nous verrons plus en détail comment modifier les états de processus, mais pour l'instant, nous pouvons reprendre l'exécution de la commande au premier plan en tapant:

fg

Une fois le processus repris, terminez-le avecCTRL-C:

CTRL-C

Gestion des processus en arrière-plan

La principale alternative à l'exécution d'un processus au premier plan est de lui permettre de s'exécuter en arrière-plan. Un processus en arrière-plan est associé au terminal spécifique qui l'a démarré, mais ne bloque pas l'accès au shell. Au lieu de cela, il s'exécute en arrière-plan, permettant à l'utilisateur d'interagir avec le système pendant l'exécution de la commande.

En raison de la manière dont les processus de premier plan interagissent avec son terminal, il ne peut y avoir qu'un seul processus de premier plan pour chaque fenêtre de terminal. Etant donné que les processus en arrière-plan rendent le contrôle au shell immédiatement sans attendre la fin du processus, de nombreux processus en arrière-plan peuvent s'exécuter simultanément.

Processus de démarrage

Vous pouvez démarrer un processus en arrière-plan en ajoutant un caractère esperluette ("&") à la fin de vos commandes. Cela indique au shell de ne pas attendre la fin du processus, mais de commencer l'exécution et de renvoyer immédiatement l'utilisateur à une invite. La sortie de la commande sera toujours affichée dans le terminal (saufredirected), mais vous pouvez taper des commandes supplémentaires pendant que le processus d'arrière-plan se poursuit.

Par exemple, nous pouvons démarrer le même processus ping à partir de la dernière section en arrière-plan en tapant:

command ping -i 5 google.com &

Vous verrez la sortie du système de contrôle des travaux debash qui ressemble à ceci:

Output[1] 4287

Vous verrez également la sortie normale de la commandeping:

OutputPING google.com (74.125.226.71) 56(84) bytes of data.
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=1 ttl=55 time=12.3 ms
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=2 ttl=55 time=11.1 ms
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=3 ttl=55 time=9.98 ms

Cependant, vous pouvez également taper des commandes en même temps. La sortie du processus d’arrière-plan sera mélangée entre l’entrée et la sortie de vos processus de premier plan, mais elle n’interférera pas avec l’exécution des processus de premier plan.

Liste des processus en arrière-plan

Pour voir tous les processus arrêtés ou en arrière-plan, vous pouvez utiliser la commandejobs:

jobs

Si la commandeping s'exécute en arrière-plan, vous verrez quelque chose qui ressemble à ceci:

Output[1]+  Running                 command ping -i 5 google.com &

Cela montre que nous avons actuellement un seul processus d'arrière-plan en cours d'exécution. Le[1] représente la «spécification de tâche» ou le numéro de tâche de la commande. Nous pouvons faire référence à cela avec d'autres commandes de contrôle des tâches et des processus, commekill,fg etbg en faisant précéder le numéro de tâche d'un signe de pourcentage. Dans ce cas, nous ferions référence à cette tâche en tant que%1.

Arrêt des processus en arrière-plan

Nous pouvons arrêter le processus d'arrière-plan actuel de plusieurs manières. Le moyen le plus simple consiste à utiliser la commandekill avec le numéro de tâche associé. Par exemple, nous pouvons tuer notre processus d'arrière-plan en cours d'exécution en tapant:

kill %1

Selon la configuration de votre terminal, le statut de fin du travail s'affiche immédiatement ou au prochain appui sur ENTER:

Output[1]+  Terminated              command ping -i 5 google.com

Si nous vérifions à nouveau la commandejobs, nous ne verrons aucune tâche en cours.

Modification des états de processus

Maintenant que nous savons comment démarrer et arrêter des processus en arrière-plan, nous pouvons parler de la façon de changer leur état.

Nous avons démontré un changement d'état plus tôt lorsque nous avons décrit comment arrêter ou suspendre un processus avecCTRL-Z. Lorsque les processus sont dans cet état arrêté, nous pouvons déplacer un processus de premier plan vers l'arrière-plan ou inversement.

Déplacer les processus de premier plan vers l'arrière-plan

Si nous oublions de terminer une commande avec& lorsque nous la démarrons, nous pouvons toujours déplacer le processus vers l'arrière-plan.

La première étape consiste à arrêter à nouveau le processus avecCTRL-Z:

CTRL-Z

Une fois le processus arrêté, nous pouvons utiliser la commandebg pour le redémarrer en arrière-plan:

bg

Vous verrez à nouveau la ligne d'état du travail, cette fois avec l'esperluette ajoutée:

Output[1]+ ping -i 5 google.com &

Par défaut, la commandebg opère sur le processus le plus récemment arrêté. Si vous avez arrêté plusieurs processus à la suite sans les redémarrer, vous pouvez référencer le processus par numéro de travail afin de l’appuyer en arrière-plan.

Notez que toutes les commandes ne peuvent pas être en arrière-plan. Certains processus se termineront automatiquement s'ils détectent qu'ils ont été démarrés avec leurs entrées et sorties standard directement connectées à un terminal actif.

Déplacer les processus en arrière-plan au premier plan

Nous pouvons également déplacer les processus d'arrière-plan au premier plan en tapantfg:

fg

Cela fonctionne sur votre processus le plus récent en arrière-plan (indiqué par le «» dans la sortie «+ jobs»). Il suspend immédiatement le processus et le met au premier plan. Pour spécifier un travail différent, utilisez son numéro de travail:

fg %2

Une fois qu'un travail est au premier plan, vous pouvez le tuer avecCTRL-C, le laisser se terminer ou le suspendre et le mettre à nouveau en arrière-plan.

Traiter avec SIGHUPs

Qu'un processus soit à l'arrière-plan ou à l'avant-plan, il est plutôt étroitement lié à l'instance de terminal qui l'a démarré. Lorsqu'un terminal se ferme, il envoie généralement un signal SIGHUP à tous les processus (avant-plan, arrière-plan ou arrêtés) liés au terminal. Cela signifie que les processus doivent se terminer car leur terminal de contrôle sera bientôt indisponible. Que faire si vous souhaitez fermer un terminal tout en maintenant les processus en arrière-plan en cours d'exécution?

Il y a plusieurs façons d'accomplir cela. Les moyens les plus flexibles sont généralement d'utiliser un multiplexeur de terminal commescreen outmux, ou d'utiliser un utilitaire qui fournit au moins la fonctionnalité de détachement de ceux-ci, commedtach.

Cependant, ce n’est pas toujours une option. Parfois, ces programmes ne sont pas disponibles ou vous avez déjà démarré le processus dont vous avez besoin pour continuer à fonctionner. Parfois, ce sont trop pour ce que vous devez accomplir.

Utilisation de nohup

Si vous savez au démarrage du processus que vous souhaiterez fermer le terminal avant la fin du processus, vous pouvez le démarrer à l'aide de la commandenohup. Cela rend le processus démarré à l’abri du signal SIGHUP. Il continuera à fonctionner à la fermeture du terminal. Il sera réaffecté en tant qu'enfant du système init:

nohup ping -i 5 google.com &

Vous verrez une ligne qui ressemble à ceci, indiquant que la sortie de la commande sera écrite dans un fichier appelénohup.out (dans le répertoire courant si accessible en écriture, sinon dans votre répertoire personnel):

Outputnohup: ignoring input and appending output to ‘nohup.out’

Cela garantit que la sortie n'est pas perdue si la fenêtre du terminal est fermée.

Si vous fermez la fenêtre du terminal et en ouvrez une autre, le processus sera toujours en cours d'exécution. Vous ne le verrez pas dans la sortie de la commandejobs car chaque instance de terminal gère sa propre file d'attente de travaux indépendante. La fermeture du terminal a provoqué la destruction despingjob même si lespingprocess sont toujours en cours d'exécution.

Pour tuer le processus deping, vous devrez rechercher son ID de processus (ou «PID»). Vous pouvez le faire avec la commandepgrep (il existe également une commandepkill, mais cette méthode en deux parties garantit que nous ne tuons que le processus prévu). Utilisezpgrep et l'indicateur-a pour rechercher l'exécutable:

pgrep -a ping
Output7360 ping -i 5 google.com

Vous pouvez ensuite arrêter le processus en référençant le PID renvoyé, qui correspond au numéro figurant dans la première colonne:

kill 7360

Vous souhaiterez peut-être supprimer le fichiernohup.out si vous n’en avez plus besoin.

Utiliser désavoué

La commandenohup est utile, mais seulement si vous savez que vous en aurez besoin au moment où vous démarrez le processus. Le système de contrôle des travaux debash fournit d'autres méthodes pour obtenir des résultats similaires avec la commande intégréedisown.

La commandedisown, dans sa configuration par défaut, supprime un travail de la file d'attente des travaux d'un terminal. Cela signifie qu'il ne peut plus être géré à l'aide des mécanismes de contrôle des travaux décrits dans ce guide (commefg,bg,CTRL-Z,CTRL-C). Il sera immédiatement retiré de la liste dans la sortiejobs et ne sera plus associé au terminal.

La commande est appelée en spécifiant un numéro de travail. Par exemple, pour rejeter immédiatement le travail 2, nous pourrions taper:

disown %2

Cela laisse le processus dans un état semblable à celui d'un processusnohup après la fermeture du terminal de contrôle. L'exception est que toute sortie sera perdue à la fermeture du terminal de contrôle si elle n'est pas redirigée vers un fichier.

Généralement, vous ne souhaitez pas supprimer complètement le processus du contrôle des travaux si vous ne fermez pas immédiatement la fenêtre de votre terminal. Vous pouvez passer l'indicateur-h au processusdisown à la place afin de marquer le processus pour ignorer les signaux SIGHUP, mais pour continuer autrement comme un travail normal:

disown -h %1

Dans cet état, vous pouvez utiliser des mécanismes de contrôle de travaux normaux pour continuer à contrôler le processus jusqu'à la fermeture du terminal. Une fois de plus, lors de la fermeture du terminal, vous serez bloqué par un processus qui n’a nulle part où sortir si vous n’avez pas redirigé vers un fichier lors du démarrage.

Pour contourner ce problème, vous pouvez essayer de rediriger la sortie de votre processus après son exécution. Cela sort du cadre de ce guide, mais vous pouvez jeter un œil àthis post pour avoir une idée de la façon dont vous le feriez.

Utilisation de l'option shell huponexit

Bash propose également un autre moyen d'éviter le problème SIGHUP pour les processus enfants. L'option shellhuponexit contrôle si bash enverra à ses processus fils le signal SIGHUP quand il sortira.

Note

[.Remarque]##

L'optionhuponexit affecte uniquement le comportement SIGHUP lorsqu'une fin de session shell est initiéefrom within the shell itself. Quelques exemples de cas où cela s'applique est lorsque la commandeexit ouCTRL-D est frappée dans la session.

Lorsqu'une session shell se termine via le programme terminal lui-même (en fermant la fenêtre, etc.), la commandehuponexit aura un effetno. Au lieu quebash décide d'envoyer ou non le signal SIGHUP, le terminal lui-même enverra le signal SIGHUP àbash, qui propagera alors (correctement) le signal à ses processus enfants.

Malgré les mises en garde ci-dessus, l'optionhuponexit est peut-être l'une des plus simples. Vous pouvez voir si cette fonctionnalité est activée ou désactivée en tapant:

shopt huponexit

Pour l'activer, tapez:

shopt -s huponexit

Maintenant, si vous quittez votre session en tapantexit, vos processus continueront tous de s'exécuter:

exit

Cette option comporte les mêmes mises en garde concernant la sortie du programme que la dernière, alors assurez-vous d’avoir redirigé la sortie de vos processus si cela est important avant de fermer votre terminal.

Conclusion

L'apprentissage du contrôle des tâches et de la gestion des processus de premier plan et d'arrière-plan vous offrira une plus grande flexibilité lors de l'exécution de programmes sur la ligne de commande. Au lieu d'avoir à ouvrir plusieurs fenêtres de terminal ou sessions SSH, vous pouvez souvent vous débrouiller avec quelques commandes d'arrêt et d'arrière-plan.