Comment exécuter et contrôler les processus d’arrière-plan sous Linux



Découvrez comment manipuler les processus en avant-plan et en arrière-plan grâce au shell Bash sous Linux. Les fonctions de contrôle des tâches et les signaux de Bash vous offrent une grande flexibilité dans l’exécution de vos commandes. Voici une exploration détaillée de ces outils.

Comprendre les Processus

Dans un environnement d’exploitation de type Linux ou Unix, chaque programme en cours d’exécution est représenté par un processus. Un processus est en fait une représentation interne du programme stockée dans la mémoire de l’ordinateur. Ainsi, chaque programme actif correspond à un processus. Pratiquement tout ce qui tourne sur votre machine, y compris les éléments de votre environnement de bureau graphique (comme GNOME ou KDE) et les démons lancés au démarrage, possède son propre processus.

Cependant, certaines commandes intégrées de Bash, telles que cd, pwd et alias, n’ont pas besoin de processus distincts pour s’exécuter. Bash les gère directement dans l’instance du shell qui s’affiche dans votre terminal. Ces commandes sont rapides car elles évitent la surcharge liée à la création d’un nouveau processus. Pour consulter la liste des fonctions intégrées de Bash, vous pouvez simplement taper `help` dans votre terminal.

Les processus peuvent s’exécuter de deux façons : en avant-plan, où ils monopolisent votre terminal jusqu’à leur achèvement, ou en arrière-plan, où ils n’interfèrent pas avec l’utilisation du terminal. Cependant, même les processus en arrière-plan peuvent perturber l’expérience utilisateur s’ils génèrent des sorties à l’écran.

Illustration Pratique

Prenons l’exemple d’une simple commande ping vers le domaine toptips.fr. L’exécution de cette commande en avant-plan se fait comme suit:

ping www.howtogeek.com

Le terminal affiche le résultat du ping de manière continue. Durant ce temps, aucune autre action n’est possible dans le même terminal. Pour arrêter la commande, il faut utiliser la combinaison de touches Ctrl + C.

Ctrl+C

Comme le montre l’image, Ctrl + C interrompt l’exécution du ping qui affiche un résumé avant de se terminer.

Recommençons, mais cette fois, utilisons Ctrl + Z au lieu de Ctrl + C. La tâche ne sera pas terminée. Au lieu de cela, elle est mise en arrière-plan, ce qui nous redonne le contrôle du terminal.

ping www.howtogeek.com
Ctrl+Z

L’effet de Ctrl + Z est visible dans cette capture d’écran.

Le processus est maintenant « arrêté », c’est-à-dire temporairement suspendu, et il attend de reprendre. C’est l’équivalent d’une voiture à l’arrêt, prête à repartir, mais pas mise à la casse. Il s’agit désormais d’une tâche d’arrière-plan.

La commande `jobs` permet de lister les tâches lancées dans la session de terminal active. Ces tâches étant des processus, nous pouvons également les voir avec la commande `ps`. Comparons les sorties de ces deux commandes en utilisant l’option `T` (terminal) pour afficher uniquement les processus exécutés dans le terminal actuel. Notez qu’il n’est pas nécessaire d’utiliser le tiret `–` avec l’option `T`.

jobs
ps T

La commande `jobs` fournit les informations suivantes:

[1]: Le numéro entre crochets est l’identifiant de la tâche. On l’utilise pour manipuler la tâche avec des commandes de contrôle.
+: Le signe plus indique que c’est la tâche qui sera affectée par une commande de contrôle sans numéro de tâche spécifié. On l’appelle la tâche par défaut et c’est toujours la dernière tâche ajoutée à la liste.
Arrêté: Le processus n’est pas en cours d’exécution.
ping www.howtogeek.com: La commande qui a lancé le processus.

La commande `ps` donne les indications suivantes:

PID: L’identifiant du processus. Chaque processus a un identifiant unique.
TTY: Le terminal (pseudo-télétype) à partir duquel le processus a été lancé.
STAT: Le statut du processus.
TIME: Le temps CPU consommé par le processus.
COMMANDE: La commande qui a lancé le processus.

Voici les valeurs courantes pour la colonne `STAT`:

D: Sommeil ininterrompu. Le processus est en attente d’une opération d’entrée/sortie et ne peut pas être interrompu.
I: Inactif.
R: En cours d’exécution.
S: Sommeil interruptible.
T: Arrêté par un signal de contrôle de tâche.
Z: Processus zombie. Le processus a été terminé mais n’a pas été nettoyé par son processus parent.

La colonne `STAT` peut aussi inclure ces indicateurs supplémentaires:

<: La tâche a une haute priorité.
N: La tâche a une basse priorité.
L: Le processus a des pages verrouillées dans la mémoire.
S: Le processus est un chef de session. Un chef de session est le processus qui a lancé un groupe de processus.
s: Le processus est un chef de session.
+: Le processus est en avant-plan. (Indique également si un processus multi-threads a un thread de premier plan.)

Nous voyons que Bash a un statut de `Ss`. Le `S` majuscule nous indique que le shell Bash est en sommeil et interruptible. Il répondra dès que nécessaire. Le `s` minuscule indique que le shell est un chef de session.

La commande `ping` a le statut `T`, ce qui indique qu’elle a été arrêtée par un signal de contrôle de tâche, dans ce cas, le Ctrl + Z que nous avons utilisé.

La commande `ps T` a le statut `R`, pour « en cours d’exécution ». Le signe `+` indique qu’il s’agit d’un membre du groupe de premier plan. Par conséquent, la commande `ps T` s’exécute en avant-plan.

La Commande `bg`

La commande `bg` sert à reprendre l’exécution d’un processus en arrière-plan. Elle peut être utilisée avec ou sans numéro de tâche. Sans numéro, c’est la tâche par défaut qui est reprise. Le processus continue de s’exécuter en arrière-plan, sans possibilité d’interaction.

Si nous utilisons la commande `bg`, la commande `ping` reprend son exécution:

bg

La commande ping reprend son exécution, et nous voyons de nouveau sa sortie dans le terminal. La commande qui a été redémarrée est affichée comme le montre la capture d’écran.

Cependant, nous avons un problème. La tâche s’exécute en arrière-plan et n’accepte aucune saisie. Comment l’arrêter ? Ctrl + C ne produit aucun effet. Nous le voyons s’afficher, mais la tâche d’arrière-plan n’est pas affectée par nos saisies et continue de faire des pings.

Nous sommes en quelque sorte dans un mode hybride. Nous pouvons taper dans le terminal, mais ce que nous écrivons est rapidement balayé par la sortie de la commande ping. Nos saisies sont interprétées en avant-plan.

Pour arrêter notre tâche d’arrière-plan, il faut la ramener en avant-plan, puis l’arrêter.

La Commande `fg`

La commande `fg` permet de ramener une tâche d’arrière-plan en avant-plan. Tout comme `bg`, elle peut être utilisée avec ou sans numéro de tâche. Avec un numéro de tâche, elle affecte la tâche spécifique. Sans numéro, c’est la dernière tâche envoyée en arrière-plan qui est affectée.

Si nous tapons `fg`, notre commande ping est ramenée en avant-plan. Les caractères que nous tapons sont mélangés avec la sortie du `ping`, mais ils sont interprétés par le shell comme si nous les avions saisis directement en ligne de commande. De fait, du point de vue du shell Bash, c’est exactement ce qui se passe.

fg

Maintenant que la commande `ping` est de nouveau en avant-plan, nous pouvons utiliser Ctrl + C pour la terminer.

Ctrl+C

Signaux et Contrôle des Processus

Ce n’était pas une expérience très fluide. Il est clair que l’exécution en arrière-plan est plus appropriée pour les processus qui ne produisent pas de sortie et n’attendent pas d’entrée.

Néanmoins, notre exemple a permis de :

Placer un processus en arrière-plan.
Reprendre son exécution en arrière-plan.
Le ramener en avant-plan.
Y mettre fin.

Les raccourcis clavier Ctrl + C et Ctrl + Z sont des moyens simplifiés d’envoyer des signaux aux processus, équivalents à la commande `kill`. Il existe 64 signaux différents que `kill` peut envoyer. Vous pouvez afficher la liste en utilisant `kill -l` en ligne de commande. Ces signaux ne sont pas uniquement envoyés par `kill`. Certains sont générés automatiquement par d’autres processus.

Voici quelques-uns des signaux les plus courants :

SIGHUP: Signal 1. Automatiquement envoyé à un processus lorsque son terminal est fermé.
SIGINT: Signal 2. Envoyé lorsqu’on appuie sur Ctrl + C. Interrompt le processus et lui demande de se terminer.
SIGQUIT: Signal 3. Envoyé lorsque l’utilisateur envoie un signal d’arrêt avec Ctrl + D.
SIGKILL: Signal 9. Le processus est immédiatement arrêté, sans tentative de fermeture propre. Le processus n’est pas arrêté de manière élégante.
SIGTERM: Signal 15. Signal par défaut envoyé par `kill`. Il signale une terminaison normale du programme.
SIGTSTP: Signal 20. Envoyé au processus lorsqu’on utilise Ctrl + Z. Arrête le processus et le place en arrière-plan.

Il est nécessaire d’utiliser la commande `kill` pour envoyer les signaux qui n’ont pas de raccourcis clavier associés.

Contrôle Avancé des Tâches

Un processus mis en arrière-plan avec Ctrl + Z est placé à l’état « arrêté ». Il faut utiliser `bg` pour le redémarrer. Il est très simple de lancer un programme comme un processus d’arrière-plan en cours d’exécution : il suffit d’ajouter un esperluette `&` à la fin de la ligne de commande.

Même si idéalement les processus en arrière-plan ne devraient pas écrire dans le terminal, nous allons utiliser des exemples qui le font, pour que les captures d’écran aient un repère visuel. Cette commande lancera une boucle infinie en arrière-plan:

Le terminal affiche le numéro de tâche et l’identifiant du processus. Dans ce cas, le numéro de tâche est 1 et l’identifiant de processus est 1979. Ces identifiants sont utilisés pour manipuler le processus.

La sortie de la boucle infinie commence à apparaître dans le terminal. Comme précédemment, nous pouvons utiliser la ligne de commande, mais toute commande est entrecoupée de la sortie du processus.

ls

Pour arrêter ce processus, nous utilisons la commande `jobs` pour obtenir le numéro de tâche, puis la commande `kill`.

La commande `jobs` nous indique que notre processus est la tâche numéro 1. Pour utiliser ce numéro avec `kill`, il faut le faire précéder du symbole pourcent `%`.

jobs
kill %1

La commande `kill` envoie le signal SIGTERM, le signal numéro 15, au processus, qui se termine. La prochaine fois que vous appuierez sur Entrée, le statut de la tâche s’affichera et indiquera que le processus est « Terminé ». Si le processus ne répond pas à la commande `kill`, il est possible d’augmenter l’agressivité. Utilisez `kill` avec SIGKILL, signal numéro 9, en insérant le numéro `9` entre `kill` et le numéro de tâche.

kill 9 %1

Récapitulatif des Outils de Contrôle

Les commandes et combinaisons de touches suivantes ont été abordées :

Ctrl + C: Envoie SIGINT, signal 2, au processus, s’il accepte une entrée, et lui demande de se terminer.
Ctrl + D: Envoie SIGQUIT, signal 3, au processus, s’il accepte une entrée, et lui demande de quitter.
Ctrl + Z: Envoie SIGSTP, signal 20, au processus et lui demande de s’arrêter et de passer en arrière-plan.
`jobs`: Affiche les tâches d’arrière-plan et leur numéro.
`bg numéro_tâche`: Redémarre un processus en arrière-plan. Si aucun numéro de tâche n’est spécifié, le dernier processus mis en arrière-plan est utilisé.
`fg numéro_tâche`: Place un processus d’arrière-plan en avant-plan et le redémarre. Si aucun numéro de tâche n’est spécifié, le dernier processus mis en arrière-plan est utilisé.
`ligne_de_commande &`: L’ajout d’une esperluette à la fin d’une ligne de commande exécute cette commande en arrière-plan et en cours d’exécution.
`kill %numéro_tâche`: Envoie SIGTERM, signal 15, au processus pour le terminer.
`kill 9 %numéro_tâche`: Envoie SIGKILL, signal 9, au processus et le termine brutalement.