Ce tutoriel donne des détails sur ce que sont les processus, comment ils sont utilisés et comment ils peuvent être gérés sous Linux.
En tant qu'administrateur système, vous avez probablement interagi avec des processus de nombreuses façons différentes.
Parfois, vous pourriez vouloir exécuter des commandes afin d'identifier les processus qui consomment beaucoup de ressources sur votre hôte.
Vous avez peut-être reçu un appel d'un utilisateur indiquant que l'un de ses processus s'est bloqué et que vous devez le tuer pour continuer à travailler.
Les processus sont vraiment au centre du système d'exploitation Linux : créés par le Kernel lui-même, ils représentent les opérations en cours d'exécution sur votre hôte Linux.
Les processus sont partout, ils peuvent s'exécuter en arrière-plan ou vous pouvez choisir de les initialiser vous-même pour des opérations personnalisées.
Vous pouvez choisir de les démarrer, de les interrompre, de les reprendre ou de les arrêter.
Dans le tutoriel d'aujourd'hui, nous examinons de très près les processus, ce qu'ils sont et comment ils sont utilisés sur notre système d'exploitation.
Nous découvrirons toutes les commandes associées aux processus, ce que sont les signaux et comment nous pouvons attribuer plus de ressources de calcul à nos processus existants.
Prêt ?
En lisant ce tutoriel jusqu'à la fin, vous apprendrez les concepts suivants :
C'est un programme assez long, alors sans plus attendre, commençons par une brève description de ce que sont les processus.
En bref, les processus sont des programmes en cours d'exécution sur votre hôte Linux qui effectuent des opérations telles que l'écriture sur un disque, l'écriture dans un fichier ou l'exécution d'un serveur web par exemple.
Les processus ont un propriétaire et ils sont identifiés par un identifiant de processus (également appelé PID).
D'autre part, les programmes sont des lignes de code ou des lignes d'instructions machine stockées sur un stockage de données persistant.
Ils peuvent simplement résider sur votre stockage de données, ou ils peuvent être en cours d'exécution, c'est-à-dire fonctionner comme des processus.
Pour effectuer les opérations qui leur sont assignées, les processus ont besoin de ressources : temps CPU, mémoire (comme la RAM ou l'espace disque), mais aussi de la mémoire virtuelle comme l'espace swap au cas où votre processus deviendrait trop gourmand.
Évidemment, les processus peuvent être démarrés, arrêtés, interrompus et même tués.
Avant d'émettre des commandes, voyons comment les processus sont créés et gérés par le noyau lui-même.
Comme nous l'avons déjà indiqué, les processus sont gérés par le Kernel sous Linux.
Cependant, il y a un concept fondamental que vous devez comprendre pour savoir comment Linux crée des processus.
Par défaut, lorsque vous démarrez un système Linux, votre noyau Linux est chargé en mémoire, il reçoit un système de fichiers virtuel dans la RAM (également appelé initramfs) et les commandes initiales sont exécutées.
L'une de ces commandes démarre le tout premier processus sur Linux.
Historiquement, ce processus était appelé le processus init, mais il a été remplacé par le processus d'initialisation systemd sur de nombreuses distributions Linux récentes.
Pour le prouver, exécutez la commande suivante sur votre hôte :
$ ps -aux | head -n 2
Comme vous pouvez le voir, le processus systemd a un PID de 1.
Si vous deviez imprimer tous les processus sur votre système, en utilisant un affichage en arbre, vous verriez que tous les processus sont des enfants du processus systemd.
$ pstree
Il est important de souligner que toutes ces étapes d'initialisation (à l'exception du lancement du processus initial) sont effectuées dans un espace réservé appelé l'espace noyau.
L'espace noyau est un espace réservé au Kernel afin qu'il puisse exécuter correctement les outils système essentiels et s'assurer que tout votre hôte fonctionne de manière cohérente.
D'autre part, l'espace utilisateur est réservé aux processus lancés par l'utilisateur et gérés par le noyau lui-même.
Par conséquent, le processus systemd est le tout premier processus lancé dans l'espace utilisateur.
Lorsque vous créez et exécutez un programme sous Linux, cela implique généralement deux étapes principales : fork et execute.
Fork est une opération de clonage, elle prend le processus actuel, également appelé processus parent, et le clone dans un nouveau processus avec un tout nouvel identifiant de processus.
Lors du fork, tout est copié depuis le processus parent : la pile, le tas, mais aussi les descripteurs de fichier, ce qui signifie l'entrée standard, la sortie standard et l'erreur standard.
Cela signifie que si mon processus parent écrivait sur la console du shell actuel, le processus enfant écrira également sur la console du shell.
L'exécution du processus cloné commencera également à la même instruction que le processus parent.
L'opération execute est utilisée sous Linux pour remplacer l'image du processus actuel par l'image d'un autre processus.
Sur le diagramme précédent, nous avons vu que la pile du processus parent contenait trois instructions restantes.
Par conséquent, les instructions ont été copiées vers le nouveau processus, mais elles ne sont pas pertinentes pour ce que nous voulons exécuter.
L'opération exec remplacera l'image du processus (c'est-à-dire l'ensemble des instructions qui doivent être exécutées) par une autre.
Si vous deviez exécuter la commande exec dans votre terminal bash, votre shell se terminerait dès que la commande est terminée car votre image de processus actuelle (votre interpréteur bash) serait remplacée par le contexte de la commande que vous essayez de lancer.
$ exec ls -l
Si vous deviez tracer les appels système effectués lors de la création d'un processus, vous trouveriez que la première commande C appelée est celle d'exec.
Lorsque vous lancez une console shell, les mêmes principes s'appliquent lorsque vous lancez une commande.
Une console shell est un processus qui attend une entrée de l'utilisateur.
Elle lance également un interpréteur bash lorsque vous appuyez sur Entrée et fournit un environnement pour que vos commandes s'exécutent.
Mais le shell suit les étapes que nous avons décrites précédemment.
Lorsque vous appuyez sur entrée, le shell est forké vers un processus enfant qui sera responsable de l'exécution de votre commande. Le shell attendra patiemment jusqu'à ce que l'exécution du processus enfant se termine.
D'autre part, le processus enfant est lié aux mêmes descripteurs de fichier et peut partager des variables qui ont été déclarées dans une portée globale.
Le processus enfant exécute la commande "exec" afin de remplacer l'image du processus actuel (qui est l'image du processus shell) par l'image du processus de la commande que vous essayez d'exécuter.
Le processus enfant finira par se terminer et imprimera son résultat sur la sortie standard qu'il a héritée du processus parent, dans ce cas, la console shell elle-même.
Maintenant que vous avez quelques notions de base sur la façon dont les processus sont créés dans votre environnement Linux, voyons quelques détails sur les processus et comment ils peuvent être facilement identifiés.
La façon la plus simple d'identifier les processus en cours d'exécution sous Linux est d'exécuter la commande ps.
$ ps
Par défaut, la commande ps vous montrera la liste des processus en cours d'exécution appartenant à l'utilisateur actuel.
Dans ce cas, seuls deux processus sont en cours d'exécution pour mon utilisateur : l'interpréteur bash et la commande ps que j'ai exécutée.
La partie importante ici est que les processus ont des propriétaires, la plupart du temps l'utilisateur qui les a exécutés en premier lieu.
Pour illustrer cela, examinons la liste des dix premiers processus sur votre système d'exploitation Linux, avec un format d'affichage différent.
$ ps -ef | head -n 10
Comme vous pouvez le voir ici, les dix premiers processus appartiennent à l'utilisateur "root".
Cette information sera particulièrement importante lorsqu'il s'agira d'interagir avec les processus à l'aide de signaux.
Pour afficher les processus qui sont détenus et exécutés par l'utilisateur connecté actuel, exécutez la commande suivante :
$ ps u
Il existe de nombreuses options différentes pour la commande ps, et elles peuvent être consultées en exécutant la commande manuel.
$ man ps
D'expérience, les deux commandes les plus importantes pour voir les processus en cours d'exécution sont :
ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
Qui correspond à une liste de processus de style BSD, alors que la commande suivante :
ps -ef
UID PID PPID C STIME TTY TIME CMD
Correspond à une liste de processus de style POSIX.
Elles représentent toutes deux les processus en cours d'exécution sur un système, mais la première a l'option "u" pour "orientée utilisateur", ce qui facilite la lecture des métriques de processus.
Maintenant que vous avez vu ce que sont les processus et comment ils peuvent être listés, voyons ce que sont les processus d'arrière-plan et de premier plan sur votre hôte.
La définition des processus d'arrière-plan et de premier plan est assez explicite.
Un processus d'arrière-plan sous Linux est un processus qui s'exécute en arrière-plan, ce qui signifie qu'il n'est pas activement géré par un utilisateur via un shell par exemple.
À l'opposé, un processus de premier plan est un processus avec lequel on peut interagir via une entrée directe de l'utilisateur.
Supposons par exemple que vous ayez ouvert un terminal shell et que vous ayez tapé la commande suivante dans votre console.
$ sleep 10000
Comme vous l'avez probablement remarqué, votre terminal se bloquera jusqu'à la fin du processus sleep. Par conséquent, le processus n'est pas exécuté en arrière-plan, il est exécuté au premier plan.
Je peux interagir avec lui. Si j'appuie sur Ctrl + Z, cela enverra directement un signal d'arrêt au processus par exemple.
Cependant, il existe un moyen d'exécuter le processus en arrière-plan.
Pour exécuter un processus en arrière-plan, mettez simplement un signe "&" à la fin de votre commande.
$ sleep 10000 &
Comme vous pouvez le voir, le contrôle a été directement rendu à l'utilisateur et le processus a commencé à s'exécuter en arrière-plan.
Pour voir votre processus en cours d'exécution, dans le contexte du shell actuel, vous pouvez exécuter la commande jobs :
$ jobs
Les jobs sont une liste de processus qui ont été démarrés dans le contexte du shell actuel et qui peuvent encore être en cours d'exécution en arrière-plan.
Comme vous pouvez le voir dans l'exemple ci-dessus, j'ai deux processus actuellement en cours d'exécution en arrière-plan.
Les différentes colonnes de gauche à droite représentent l'ID de job, l'état du processus (que vous découvrirez dans la section suivante) et la commande exécutée.
Pour interagir avec les jobs, vous disposez de deux commandes : bg et fg.
La commande bg est utilisée sous Linux pour envoyer un processus en arrière-plan et la syntaxe est la suivante :
$ bg %<job_id>
De même, pour envoyer un processus au premier plan, vous pouvez utiliser fg de la même manière :
$ fg %<job_id>
Si nous revenons à la liste des jobs de notre exemple précédent, si je veux amener le job 3 au premier plan, c'est-à-dire à la fenêtre du shell actuel, j'exécuterais la commande suivante :
$ fg %3
En émettant une commande Ctrl + Z, je peux arrêter le processus. Je peux le lier à une commande bg pour l'envoyer en arrière-plan.
Maintenant que vous avez une meilleure idée de ce que sont les processus d'arrière-plan et de premier plan, voyons comment il est possible d'interagir avec les processus à l'aide de signaux.
Sous Linux, les signaux sont une forme de communication interprocessus (également appelée IPC) qui crée et envoie des notifications asynchrones aux processus en cours d'exécution concernant l'occurrence d'un événement spécifique.
Les signaux sont souvent utilisés pour envoyer une commande de kill ou de terminaison à un processus afin de l'arrêter (également appelé signal kill).
Pour envoyer un signal à un processus, vous devez utiliser la commande kill.
$ kill -<numéro du signal> <pid>|<nom_du_processus>
Par exemple, pour forcer un processus HTTPD (PID = 123) à se terminer (sans arrêt propre), vous exécuteriez la commande suivante :
$ kill -9 123
Comme expliqué, il existe de nombreux signaux qu'on peut envoyer pour notifier un processus spécifique.
Voici la liste des plus couramment utilisés :
Pour voir la liste complète de tous les signaux disponibles, vous pouvez exécuter la commande suivante :
$ kill -l
Maintenant que vous savez qu'il est possible d'interrompre, de tuer ou d'arrêter des processus, il est temps d'en apprendre davantage sur les états des processus.
Les processus ont de nombreux états différents, ils peuvent être :
Voici un diagramme qui représente les différents états des processus liés aux signaux que vous pouvez leur envoyer.
Maintenant que vous en savez un peu plus sur les états des processus, examinons les commandes pgrep et pkill.
Sous Linux, il y a déjà beaucoup que vous pouvez faire en utilisant simplement la commande ps.
Vous pouvez restreindre votre recherche à un processus particulier, et vous pouvez utiliser le PID pour le tuer complètement.
Cependant, il existe deux commandes qui ont été conçues pour que vos commandes soient encore plus courtes : pgrep et pkill.
La commande pgrep est un raccourci pour utiliser la commande ps suivie de la commande grep.
La commande pgrep recherchera toutes les occurrences d'un processus spécifique en utilisant un nom ou un modèle défini.
La syntaxe de la commande pgrep est la suivante :
$ pgrep <options> <pattern>
Par exemple, si vous deviez rechercher tous les processus nommés "bash" sur votre hôte, vous exécuteriez la commande suivante :
$ pgrep bash
La commande pgrep n'est pas limitée par défaut aux processus appartenant à l'utilisateur actuel.
Si un autre utilisateur devait exécuter la commande bash, elle apparaîtrait dans la sortie de la commande pgrep.
Il est également possible de rechercher des processus en utilisant des caractères de globbing.
D'autre part, la commande pkill est également un raccourci pour la commande ps utilisée avec la commande kill.
La commande pkill est utilisée pour envoyer un signal aux processus en fonction de leurs identifiants ou de leurs noms.
La syntaxe de la commande pkill est la suivante :
$ pkill <options> <pattern>
Par exemple, si vous voulez tuer toutes les fenêtres Firefox sur votre hôte, vous exécuteriez la commande suivante :
$ pkill firefox
De manière similaire à la commande pgrep, vous avez la possibilité de restreindre vos résultats en spécifiant un utilisateur avec l'option -u.
Pour tuer tous les processus commençant par "fire" et appartenant à l'utilisateur actuel et root, vous exécuteriez la commande suivante :
$ pkill user,root fire*
Si vous n'avez pas les droits pour arrêter un processus, vous obtiendrez un message d'erreur de permission refusée sur votre sortie standard.
Vous avez également la possibilité d'envoyer des signaux spécifiques en spécifiant le numéro du signal dans la commande pkill.
Par exemple, pour arrêter Firefox avec un signal SIGSTOP, vous exécuteriez la commande suivante :
$ pkill -19 firefox
Sous Linux, tous les processus ne reçoivent pas la même priorité en ce qui concerne le temps CPU.
Certains processus, comme les processus très importants exécutés par root, reçoivent une priorité plus élevée afin que le système d'exploitation travaille sur des tâches qui importent vraiment au système.
La priorité des processus sous Linux est appelée le niveau de nice.
Le niveau de nice est une échelle de priorité allant de -20 à 19.
Plus vous descendez sur l'échelle de nice, plus la priorité sera élevée.
De même, plus vous êtes haut sur l'échelle de nice, plus votre priorité sera basse.
Pour vous en souvenir, vous pouvez vous rappeler que "plus vous êtes gentil, plus vous êtes prêt à partager les ressources avec les autres".
Pour démarrer un certain programme ou processus avec un niveau de nice donné, vous exécuterez la commande suivante :
$ nice -n <level> <command>
Par exemple, pour exécuter la commande tar avec un niveau tar personnalisé, vous exécuteriez la commande suivante :
$ nice -n 19 tar -cvf test.tar file
De même, vous pouvez utiliser la commande renice pour définir le niveau de nice d'un processus en cours d'exécution à une valeur donnée.
$ renice -n <priority> <pid>
Par exemple, si j'ai un processus en cours d'exécution avec le PID 123, je peux utiliser la commande renice pour définir sa priorité à une valeur donnée.
$ renice -n 18 123
Si vous n'êtes pas membre du groupe sudo (ou membre du groupe wheel sur les distributions basées sur Red Hat), il y a des restrictions en ce qui concerne ce que vous pouvez faire avec la commande nice.
Pour l'illustrer, essayez d'exécuter la commande suivante en tant qu'utilisateur non-sudo :
$ nice -n -1 tar -cvf test.tar file
Quand il s'agit de nice, il y a une règle que vous devez connaître :
En tant qu'utilisateur non-root (ou sudo), vous ne pourrez pas définir un niveau de nice inférieur à celui par défaut (qui est zéro), et vous ne pourrez pas renice un processus en cours d'exécution à un niveau inférieur au niveau actuel.
Pour illustrer ce dernier point, lancez une commande sleep en arrière-plan avec une valeur de nice de 2.
$ nice -n 2 sleep 10000 &
Ensuite, identifiez l'identifiant du processus que vous venez de créer.
Maintenant, essayez de définir le niveau de nice de votre processus à une valeur inférieure à celle que vous avez spécifiée en premier lieu.
$ renice -n 1 8363
Comme vous l'avez probablement remarqué, vous ne pourrez pas définir le niveau de nice à 1, mais seulement à une valeur supérieure à celle que vous avez spécifiée.
Maintenant, si vous choisissez d'exécuter la commande en tant que sudo, vous pourrez définir le niveau de nice à une valeur inférieure.
Maintenant que vous avez une idée claire des commandes nice et renice, voyons comment vous pouvez surveiller vos processus en temps réel sous Linux.
Dans un article précédent, nous avons discuté de la façon dont il est possible de construire un pipeline de surveillance complet afin de surveiller les processus Linux en temps réel.
Top est une commande interactive que tout utilisateur peut exécuter afin d'avoir une liste complète et ordonnée de tous les processus en cours d'exécution sur un hôte Linux.
Pour exécuter top, exécutez-le simplement sans aucun argument.
Top s'exécutera en mode interactif.
$ top
Si vous voulez exécuter top pour un nombre personnalisé d'itérations, exécutez la commande suivante :
$ top -n <number>
La commande top affichera d'abord des statistiques récapitulatives sur votre système en haut, par exemple le nombre de tâches en cours d'exécution, le pourcentage de CPU utilisé ou la consommation de mémoire.
Juste en dessous, vous avez accès à une liste en direct de tous les processus en cours d'exécution ou en sommeil sur votre hôte.
Cette vue se rafraîchira toutes les trois secondes, mais vous pouvez évidemment modifier ce paramètre.
Pour augmenter la fréquence de rafraîchissement dans la commande top, appuyez sur la touche "d" et choisissez une nouvelle fréquence de rafraîchissement.
De même, vous pouvez modifier la valeur de nice d'un processus en cours d'exécution en direct en appuyant sur la touche "r" de votre clavier.
Les mêmes règles de permissions s'appliquent si vous voulez modifier les processus à une valeur inférieure à celle qui leur est déjà attribuée.
Par conséquent, vous devrez peut-être exécuter la commande en tant que sudo.
Alternativement, si vous cherchez une façon plus agréable de visualiser les processus sur votre hôte Linux, vous pouvez utiliser la commande htop.
Par défaut, la commande htop n'est pas disponible sur la plupart des distributions, vous devrez donc l'installer avec les instructions suivantes.
$ sudo apt-get update
$ sudo apt-get install htop
Si vous exécutez une distribution basée sur Red Hat, exécutez les commandes suivantes.
$ sudo yum -y install epel-release
$ sudo yum -y update
$ sudo yum -y install htop
Enfin, pour exécuter la commande htop, exécutez-la simplement sans aucun argument.
$ htop
Comme vous pouvez le voir, la sortie est très similaire sauf qu'elle présente les informations d'une manière plus conviviale.
Dans ce tutoriel, vous avez appris de nombreux concepts sur les processus : comment ils sont créés, comment ils peuvent être gérés et comment ils peuvent être surveillés efficacement.
Si vous cherchez plus de tutoriels liés à l'administration système Linux, nous avons une section complète qui lui est dédiée sur le site web, alors assurez-vous de la consulter.