Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 914 minIntermédiaire

Processus et services : ps, kill, systemctl

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • observer les processus et la charge d'une machine ;
  • arrêter un processus proprement avec le bon signal ;
  • piloter un service avec systemctl et lire son état ;
  • écrire une unité systemd pour une application et la durcir ;
  • modifier un service fourni par un paquet sans toucher à son fichier.

3 exercices corrigés

Un processus est un programme en cours d'exécution, identifié par un numéro (PID) ; un service est un processus lancé au démarrage et surveillé par systemd, le premier processus du système. Ce chapitre montre comment observer les processus et la charge d'une machine, leur envoyer des signaux, puis piloter les services avec systemctl, écrire une unité systemd pour une application maison et modifier un service existant sans toucher au fichier du paquet.

Observer les processus

Chaque processus a un PID, un processus parent (PPID), un propriétaire, et consomme du processeur et de la mémoire. Le noyau les expose dans /proc/<PID>/.

CommandeCe qu'elle montre
ps auxTous les processus : utilisateur, PID, %CPU, %MEM, commande
ps -ef --forestTous les processus, avec la parenté en arbre
ps -u www-dataLes processus d'un compte
pgrep -a nginxLes PID et commandes dont le nom correspond
pstree -pL'arbre des processus depuis systemd (PID 1)
topVue en direct, triée par consommation (P processeur, M mémoire, k tuer, q quitter)
htopLa même chose, plus lisible (paquet htop)
uptimeDurée de fonctionnement et charge moyenne sur 1, 5 et 15 minutes
free -hMémoire vive et swap utilisées
console
clambert@srv-web:~$ ps aux | grep [n]ginx
root         620  0.0  0.1  11404  1640 ?        Ss   08:12   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data     621  0.0  0.3  12960  6196 ?        S    08:12   0:01 nginx: worker process
www-data     622  0.0  0.3  12960  6196 ?        S    08:12   0:01 nginx: worker process

Le processus maître de nginx tourne en root pour ouvrir le port 443, puis lance des processus de travail sous www-data, qui traitent les requêtes : c'est le moindre privilège appliqué par le logiciel lui-même. Les crochets de [n]ginx évitent que grep se trouve lui-même dans la liste.

La charge moyenne (load average) compte les processus qui s'exécutent ou attendent le processeur (ou un disque). Elle se compare au nombre de cœurs : 0.80 sur une machine à 2 cœurs, c'est calme ; 6.00 durablement, des processus font la queue. nproc affiche le nombre de cœurs.

Les signaux

On agit sur un processus en lui envoyant un signal :

SignalNuméroEffetEnvoyé par
SIGTERM15Demande de s'arrêter proprement (le programme ferme ses fichiers)kill PID (signal par défaut)
SIGKILL9Arrêt immédiat par le noyau, sans que le programme puisse réagirkill -9 PID, en dernier recours
SIGHUP1Beaucoup de services y relisent leur configurationkill -HUP PID
SIGINT2InterruptionCtrl+C
SIGSTOP / SIGCONT19 / 18Suspendre / reprendrekill -STOP, kill -CONT

pkill nginx et killall nginx envoient un signal par nom. Pour un service, on passe plutôt par systemctl stop ou systemctl kill : systemd sait quels processus appartiennent au service.

Priorité. La valeur nice va de -20 (le plus prioritaire) à 19 (le plus gentil avec les autres), 0 par défaut. nice -n 10 tar czf archive.tgz /srv/journaux lance une compression en arrière-plan sans ralentir le reste ; sudo renice -n 15 -p 2741 change la priorité d'un processus déjà lancé. Seul root peut augmenter une priorité.

Avant-plan et arrière-plan. Dans un terminal, commande & lance en arrière-plan ; Ctrl+Z suspend la commande en cours ; jobs liste, bg relance en arrière-plan, fg ramène au premier plan. Une commande lancée ainsi s'arrête quand la session SSH se ferme : pour un long traitement, utilise nohup commande &, ou mieux une session tmux qu'on retrouve après une déconnexion.

systemd et les unités

systemd est le premier processus lancé par le noyau (PID 1). Il démarre tous les autres, dans le bon ordre, les surveille, les relance s'ils s'arrêtent, et collecte leurs journaux. Il décrit chaque chose à gérer par une unité (unit), un fichier texte :

Type d'unitéSuffixeExemple
Service.servicenginx.service, ssh.service
Minuterie.timerapt-daily.timer, logrotate.timer (chapitre 15)
Point de montage.mounttmp.mount, généré pour chaque ligne de /etc/fstab
Socket.socketDémarre un service à la première connexion
Cible.targetUn groupe d'unités : multi-user.target, rescue.target

Les unités livrées par les paquets sont dans /usr/lib/systemd/system/ ; celles de l'administrateur, et ses modifications, dans /etc/systemd/system/, qui a priorité. On ne modifie jamais les fichiers de /usr/lib : une mise à jour du paquet les écraserait.

Piloter un service avec systemctl

CommandeEffet
systemctl status nginxÉtat, PID, dernières lignes du journal
sudo systemctl start nginx / stopDémarre / arrête maintenant
sudo systemctl restart nginxArrête puis redémarre (coupe les connexions en cours)
sudo systemctl reload nginxRelit la configuration sans interruption (si le service le permet)
sudo systemctl enable nginx / disableDémarre / ne démarre plus au démarrage de la machine
sudo systemctl enable --now nginxActive au démarrage et démarre maintenant
sudo systemctl mask cupsInterdit tout démarrage, même manuel ou par dépendance (unmask pour lever)
systemctl is-active nginx, is-enabled nginxRéponse d'un mot, pratique dans un script
systemctl --failedLes unités en échec
systemctl list-units --type=service --state=runningLes services qui tournent
systemctl cat nginxLe fichier de l'unité et ses surcharges
sudo systemctl daemon-reloadRelit les fichiers d'unité après une modification
console
clambert@srv-web:~$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since mer. 2026-11-04 08:12:03 CET; 1h 40min ago
       Docs: man:nginx(8)
    Process: 612 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Process: 618 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 620 (nginx)
      Tasks: 3 (limit: 2307)
     Memory: 4.1M (peak: 4.6M)
        CPU: 38ms
     CGroup: /system.slice/nginx.service
             ├─620 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             ├─621 "nginx: worker process"
             └─622 "nginx: worker process"

Trois lignes à lire en premier : Loaded dit où est le fichier et si le service est activé au démarrage (enabled) ; Active dit s'il tourne (active (running)), s'il a échoué (failed) ou s'il est arrêté (inactive (dead)) ; les dernières lignes du journal, sous le cadre, donnent souvent la cause d'un échec.

Écrire une unité pour une application

Le site de suivi des livraisons s'appuie sur une petite application (une API écrite en Python) qui écoute sur 127.0.0.1:8080, derrière nginx. Plutôt que de la lancer à la main dans un terminal, on en fait un service : elle démarrera avec la machine, sera relancée si elle plante, tournera sous un compte dédié sans privilège, et ses messages iront dans le journal.

bash
sudo adduser --system --group --home /opt/suivi suivi    # compte système dédié
sudo nano /etc/systemd/system/suivi-api.service
ini
[Unit]
Description=API du site de suivi des livraisons
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=suivi
Group=suivi
WorkingDirectory=/opt/suivi
ExecStart=/usr/bin/python3 /opt/suivi/app.py
Restart=on-failure
RestartSec=5
UMask=0027
# Durcissement : pas de nouveaux privilèges, système en lecture seule, /tmp privé
NoNewPrivileges=yes
ProtectSystem=full
ProtectHome=yes
PrivateTmp=yes

[Install]
WantedBy=multi-user.target
Section, directiveRôle
[Unit] After=, Wants=Démarrer après que le réseau est configuré
[Service] Type=simpleLe processus lancé par ExecStart est le service lui-même
User=, Group=Le compte sous lequel il tourne
Restart=on-failure, RestartSec=5Relancer 5 secondes après un plantage (pas après un arrêt demandé)
NoNewPrivileges=, ProtectSystem=, ProtectHome=, PrivateTmp=Limiter ce que le service pourrait faire s'il était détourné
[Install] WantedBy=multi-user.targetenable le rattache au démarrage normal du serveur
bash
sudo systemctl daemon-reload
sudo systemctl enable --now suivi-api
systemctl status suivi-api
journalctl -u suivi-api -f

systemd-analyze verify /etc/systemd/system/suivi-api.service vérifie la syntaxe, et systemd-analyze security suivi-api note l'exposition du service, de 0 (très protégé) à 10, avec la liste des protections qui manquent.

Modifier un service sans toucher au paquet

Pour changer le comportement d'un service fourni par un paquet, on écrit une surcharge (drop-in) : un petit fichier qui ajoute ou remplace des directives. systemctl edit la crée au bon endroit :

bash
sudo systemctl edit nginx

L'éditeur s'ouvre sur /etc/systemd/system/nginx.service.d/override.conf. On y écrit seulement ce qui change :

ini
[Service]
Restart=on-failure
RestartSec=10

À l'enregistrement, systemctl edit recharge la configuration de systemd. systemctl cat nginx affiche le fichier d'origine suivi de la surcharge. Une mise à jour du paquet nginx remplacera son fichier dans /usr/lib, jamais ta surcharge.

Les cibles et le démarrage

Une cible regroupe les unités d'un état du système. Les principales :

CibleÉtatÉquivalent historique
multi-user.targetServeur normal, multi-utilisateur, réseau, sans interface graphiqueNiveau 3
graphical.targetmulti-user + interface graphiqueNiveau 5
rescue.targetMode de secours : un seul utilisateur (root), systèmes de fichiers montés, peu de servicesNiveau 1
emergency.targetMode d'urgence : seul / est monté, en lecture seule

systemctl get-default affiche la cible de démarrage (multi-user.target sur un serveur sans bureau). systemd-analyze blame liste les unités les plus lentes au démarrage ; systemd-analyze critical-chain montre la chaîne qui a retardé l'arrivée à la cible. Le démarrage complet, de l'UEFI à la cible, est détaillé avec le dépannage au chapitre 17.

Exercices

Exercice 1 sur 3 start, enable ou reload ? Réussi À revoir

Donne la commande pour chaque situation sur srv-web :

  1. Tu viens de modifier /etc/nginx/sites-available/suivi et veux l'appliquer sans couper les visiteurs.
  2. Le service cups (impression) n'a rien à faire sur un serveur et ne doit plus jamais démarrer.
  3. Après l'installation de fail2ban, tu veux qu'il tourne maintenant et après chaque redémarrage.
  4. Tu viens de créer /etc/systemd/system/suivi-api.service ; systemctl start suivi-api répond « Unit suivi-api.service not found ».
Voir la réponseMasquer la réponse de l'exercice 1
  1. sudo nginx -t && sudo systemctl reload nginx : on teste la syntaxe, et on recharge seulement si le test réussit.
  2. sudo systemctl disable --now cups, et sudo systemctl mask cups pour qu'aucune dépendance ne puisse le relancer. Mieux encore : sudo apt purge cups.
  3. sudo systemctl enable --now fail2ban.
  4. systemd n'a pas encore lu le nouveau fichier : sudo systemctl daemon-reload, puis sudo systemctl enable --now suivi-api.

Tu avais trouvé ?

Exercice 2 sur 3 Lire un état de service Réussi À revoir

text
● suivi-api.service - API du site de suivi des livraisons
     Loaded: loaded (/etc/systemd/system/suivi-api.service; enabled; preset: enabled)
     Active: activating (auto-restart) (Result: exit-code) since mer. 2026-11-04 10:31:12 CET; 3s ago
    Process: 3310 ExecStart=/usr/bin/python3 /opt/suivi/app.py (code=exited, status=1/FAILURE)
   Main PID: 3310 (code=exited, status=1/FAILURE)

nov. 04 10:31:12 srv-web python3[3310]: PermissionError: [Errno 13] Permission denied: '/var/lib/suivi/exports'
nov. 04 10:31:12 srv-web systemd[1]: suivi-api.service: Failed with result 'exit-code'.
  1. Le service démarrera-t-il au prochain redémarrage de la machine ?
  2. Que fait systemd en ce moment ?
  3. Quelle est la cause, et comment la corriger ?
Voir la réponseMasquer la réponse de l'exercice 2
  1. Oui : enabled sur la ligne Loaded.
  2. Il attend avant de relancer le service (activating (auto-restart)), comme le demande Restart=on-failure : le programme s'est terminé avec le code 1, un échec.
  3. L'application, qui tourne sous le compte suivi, n'a pas le droit d'écrire dans /var/lib/suivi/exports. Il faut donner ce dossier au compte du service : sudo mkdir -p /var/lib/suivi/exports && sudo chown -R suivi:suivi /var/lib/suivi && sudo chmod 750 /var/lib/suivi /var/lib/suivi/exports. Une autre solution, plus propre, est la directive StateDirectory=suivi dans l'unité : systemd crée alors /var/lib/suivi au démarrage, avec le bon propriétaire.

Tu avais trouvé ?

Exercice 3 sur 3 Un processus qui ne répond plus Réussi À revoir

Un script d'export lancé à la main par Moussa Diallo (PID 4120) bloque depuis une heure et consomme 100 % d'un cœur. Décris, dans l'ordre, les commandes pour le constater et l'arrêter proprement.

Voir la réponseMasquer la réponse de l'exercice 3
  1. Constater : top (ou ps -o pid,user,%cpu,etime,cmd -p 4120) montre le processus, son propriétaire, sa consommation et sa durée.
  2. Demander l'arrêt propre : kill 4120 (SIGTERM, sans sudo puisqu'il appartient à mdiallo, qui le lance lui-même).
  3. Attendre quelques secondes, vérifier avec ps -p 4120. S'il est toujours là : kill -9 4120.
  4. Chercher la cause avant de relancer (fichier verrouillé, boucle infinie), dans la sortie du script ou dans le journal.

Tu avais trouvé ?

Chapitre terminé !

Fais les 3 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Les journaux sous Linux : journalctl, rsyslog et logrotateRevoir le sommaire du cours