🐧 Correction TP BASH

Activités 5 à 9 - Processus et Shell Linux

5Surveillance avancée des processus

Q15. Identifier le processus le plus gourmand en CPU

Utilisez htop ou top pour identifier le processus qui consomme le plus de CPU.

Correction

Avec la commande top, les processus sont triés par défaut par utilisation CPU décroissante.

$ top

Exemple de réponse :

  • Processus : python3 ou python
  • PID : 1234 (variable selon le systĂšme)
  • %CPU : 25.3% (variable selon la charge)
Sur un Raspberry Pi au repos, les processus les plus gourmands sont généralement :
  • Le serveur X11 (interface graphique)
  • Les navigateurs web (Chromium)
  • Les processus Python en cours d'exĂ©cution
Q16. Tri des processus par utilisation mémoire

Quelle commande permet de trier les processus par utilisation mémoire avec ps ?

Correction

Commande principale :

$ ps aux --sort=-%mem

Pour afficher seulement les 10 premiers :

$ ps aux --sort=-%mem | head -11

Explications :

  • aux : affiche tous les processus avec dĂ©tails
  • --sort=-%mem : trie par mĂ©moire dĂ©croissante (le - indique l'ordre dĂ©croissant)
  • On peut aussi utiliser --sort=%mem pour un tri croissant

Alternative avec sélection des colonnes :

$ ps -eo pid,user,%mem,%cpu,cmd --sort=-%mem | head -10
Q17. Compter les processus Python

Combien de processus Python sont actuellement en cours d'exécution ?

Correction

Commande pour compter :

$ pgrep python | wc -l

Pour voir les détails :

$ pgrep -a python

Exemple de réponse : 5 processus Python (si on a lancé 5 instances d'infini.py)

Avantages de pgrep :
  • Plus efficace que ps aux | grep python
  • Ne capture pas le processus grep lui-mĂȘme
  • Options avancĂ©es : -u pour filtrer par utilisateur, -l pour afficher les noms

Pour tuer tous les processus Python d'un coup :

$ pkill python

6Signaux et communication entre processus

Q18. Liste des signaux

Combien de signaux différents existe-t-il ? Notez les numéros et noms des signaux.

Correction

Il existe 64 signaux sous Linux (numérotés de 1 à 64).

Commande pour voir tous les signaux :

$ kill -l

Principaux signaux :

Signal Numéro Nom Description
Terminer proprement 15 SIGTERM Demande au processus de se terminer proprement (peut ĂȘtre interceptĂ©)
Forcer l'arrĂȘt 9 SIGKILL Force l'arrĂȘt immĂ©diat (ne peut PAS ĂȘtre interceptĂ©)
Suspendre 19 SIGSTOP Suspend le processus (ne peut PAS ĂȘtre interceptĂ©)

Autres signaux importants :

  • Signal 1 (SIGHUP) : Rechargement de la configuration (pour les dĂ©mons)
  • Signal 2 (SIGINT) : Interruption (Ă©quivalent Ă  Ctrl+C)
  • Signal 18 (SIGCONT) : Reprend un processus suspendu
  • Signal 20 (SIGTSTP) : Suspend (Ă©quivalent Ă  Ctrl+Z)
Q19. État d'un processus suspendu

Quel est l'état du processus (colonne STAT) lorsqu'il est suspendu ?

Correction

Commandes à exécuter :

# Lancer infini.py
$ python infini.py &
[1] 5432

# Suspendre le processus
$ kill -STOP 5432

# Vérifier l'état
$ ps -o pid,stat,cmd -p 5432

Résultat attendu :

PID  STAT  CMD
5432 T     python infini.py
RĂ©ponse : L'Ă©tat est T (sTopped) - le processus est suspendu/arrĂȘtĂ© temporairement.

Pour reprendre le processus :

$ kill -CONT 5432
# L'état redevient S (Sleeping) ou R (Running)

États possibles (rappel) :

  • R : Running (en cours d'exĂ©cution)
  • S : Sleeping (en attente)
  • T : sTopped (suspendu)
  • Z : Zombie (terminĂ© mais non rĂ©cupĂ©rĂ© par le parent)
  • D : Uninterruptible sleep (attente I/O)
Q20. Différence entre SIGTERM et SIGKILL

Quelle est la différence entre ces deux signaux ? Lequel devrait-on privilégier et pourquoi ?

Correction
Aspect SIGTERM (15) SIGKILL (9)
Interception ✅ Peut ĂȘtre interceptĂ© ❌ NE peut PAS ĂȘtre interceptĂ©
Nettoyage ✅ Permet la terminaison propre ❌ ArrĂȘt brutal, pas de nettoyage
Commande kill PID ou kill -15 PID kill -9 PID
Usage đŸ„‡ À privilĂ©gier en premier ⚠ En dernier recours
SIGTERM (15) :
  • Envoie une "demande polie" de terminaison
  • Le processus peut intercepter le signal et exĂ©cuter du code de nettoyage
  • Permet de fermer proprement les fichiers, connexions rĂ©seau, libĂ©rer les ressources
SIGKILL (9) :
  • Force l'arrĂȘt immĂ©diat par le noyau
  • Le processus ne peut PAS l'intercepter ni l'ignorer
  • Pas de nettoyage possible → risque de corruption de donnĂ©es
  • Peut laisser des ressources non libĂ©rĂ©es

Bonne pratique :

# 1. Essayer d'abord SIGTERM
$ kill 1234

# 2. Attendre quelques secondes (ex: 5-10s)
$ sleep 5

# 3. Si le processus ne s'est pas terminé, utiliser SIGKILL
$ kill -9 1234

7Processus zombies et orphelins

Création et détection de processus zombies

Créer un fichier zombie.py et détecter les processus zombies.

Correction - Code zombie.py
import os
import time

def main():
    pid = os.fork()
    
    if pid > 0:
        # Processus parent
        print(f"Parent (PID: {os.getpid()}) a créé l'enfant (PID: {pid})")
        time.sleep(60)  # Le parent attend sans récupérer l'enfant
    else:
        # Processus enfant
        print(f"Enfant (PID: {os.getpid()}) se termine")
        exit(0)

main()

Exécution et détection :

# Lancer le programme
$ python zombie.py

# Dans un autre terminal, détecter les zombies
$ ps aux | grep defunct
# ou
$ ps aux | grep Z
# ou plus précis
$ ps -eo pid,stat,cmd | grep Z

Résultat attendu :

1234  Z    [python] <defunct>
Q21. Qu'est-ce qu'un processus zombie ? Pourquoi existe-t-il ?
Correction
Définition :
Un processus zombie (ou defunct) est un processus qui a terminé son exécution mais dont l'entrée dans la table des processus n'a pas encore été supprimée par son processus parent.

Pourquoi existe-t-il ?

1. Cycle de vie normal d'un processus :

  • Un processus enfant se termine (exit())
  • Le noyau conserve certaines informations (code de sortie, statistiques d'utilisation)
  • Ces informations doivent ĂȘtre lues par le parent via wait() ou waitpid()
  • Une fois lues, le processus est complĂštement supprimĂ©

2. Cas du zombie :

  • L'enfant se termine
  • Le parent ne rĂ©cupĂšre pas le code de sortie (n'appelle pas wait())
  • L'enfant reste en Ă©tat zombie en attendant que le parent le rĂ©cupĂšre

3. Caractéristiques d'un zombie :

  • N'utilise aucune ressource CPU ou mĂ©moire (sauf l'entrĂ©e dans la table)
  • État : Z (Zombie) ou <defunct>
  • Ne peut pas ĂȘtre tuĂ© avec kill (il est dĂ©jĂ  mort !)
  • DisparaĂźt quand le parent appelle wait() ou se termine
SchĂ©ma du problĂšme : Parent (PID 1000) | |-- fork() --> Enfant (PID 1001) | |-- ExĂ©cution |-- exit(0) ✓ |-- État = Zombie (Z) | |-- sleep(60) ← ProblĂšme : n'appelle pas wait() | └-- wait() devrait ĂȘtre ici !
Q22. Comment peut-on éliminer un processus zombie ?
Correction

Méthodes pour éliminer un zombie :

1. Solution propre : Le parent récupÚre l'enfant

Modifier le code pour que le parent appelle wait() :

import os
import sys

def main():
    pid = os.fork()
    
    if pid > 0:
        # Processus parent
        print(f"Parent (PID: {os.getpid()}) a créé l'enfant (PID: {pid})")
        # Attendre que l'enfant se termine et récupérer son état
        child_pid, status = os.wait()
        print(f"Enfant {child_pid} terminé avec le code {status}")
    else:
        # Processus enfant
        print(f"Enfant (PID: {os.getpid()}) se termine")
        sys.exit(0)

main()

2. Tuer le processus parent

# Trouver le PID du parent
$ ps -eo pid,ppid,stat,cmd | grep defunct

# Tuer le parent
$ kill PPID_du_parent
Conséquence : Quand un processus parent meurt, ses enfants (y compris les zombies) sont adoptés par le processus init (PID 1) ou systemd, qui nettoie automatiquement les zombies.

3. On ne peut PAS tuer directement un zombie

Ces commandes NE FONCTIONNENT PAS sur un zombie :
$ kill -9 PID_zombie     # ❌ Inefficace (dĂ©jĂ  mort)
$ kill -15 PID_zombie    # ❌ Inefficace
Méthode Commande/Action Efficacité
RĂ©cupĂ©ration par le parent os.wait() dans le code ✅ Solution idĂ©ale
Gestionnaire SIGCHLD signal.signal(SIGCHLD, handler) ✅ Solution professionnelle
Tuer le parent kill PPID ⚠ Fonctionne mais brutal
Tuer le zombie kill -9 PID_zombie ❌ Impossible

8Priorités et ordonnancement

Q23. Valeurs de priorité avec nice

Lancez deux instances de infini.py avec des priorités différentes et observez les valeurs NI.

Correction

Commandes à exécuter :

# Instance avec priorité basse (moins prioritaire)
$ nice -n 10 python infini.py &
[1] 2345

# Instance avec priorité haute (plus prioritaire - nécessite sudo)
$ sudo nice -n -5 python infini.py &
[2] 2346

# Afficher les priorités
$ ps -l
Explication des valeurs nice :
  • Valeurs de -20 Ă  19
  • -20 = prioritĂ© maximale (processus trĂšs prioritaire)
  • 0 = prioritĂ© par dĂ©faut
  • 19 = prioritĂ© minimale (processus "trĂšs gentil")
  • Seul root peut dĂ©finir des valeurs nĂ©gatives (prioritĂ© haute)

Résultat attendu avec ps -l :

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY        TIME CMD
0 S  1000  2345  1234  0  90  10    -  123 -      pts/0   0:00 python infini.py
0 S  1000  2346  1234  0  75  -5    -  123 -      pts/0   0:00 python infini.py
Réponse :
  • Processus 2345 : NI = 10 (prioritĂ© basse, PRI = 90)
  • Processus 2346 : NI = -5 (prioritĂ© haute, PRI = 75)

Plus la valeur PRI est basse, plus le processus est prioritaire.

Relation entre NI et PRI :
PRI = 80 + NI (approximativement)
Le noyau calcule la priorité effective (PRI) en fonction de la valeur nice (NI) et d'autres facteurs.
Q24. Modifier la priorité d'un processus existant

Quelle commande permet de réduire la priorité d'un processus en cours ?

Correction

Commande renice :

# Rendre un processus "plus gentil" (réduire sa priorité)
$ renice +10 -p 2345

# Augmenter la priorité (nécessite sudo)
$ sudo renice -10 -p 2346

Syntaxe générale :

renice [nouvelle_valeur_nice] -p [PID]
renice [nouvelle_valeur_nice] -u [utilisateur]
renice [nouvelle_valeur_nice] -g [groupe]

Exemples pratiques :

# Réduire la priorité de tous les processus d'un utilisateur
$ sudo renice +15 -u nomeleve

# Vérifier le changement
$ ps -l -u nomeleve
Restrictions :
  • Un utilisateur normal ne peut qu'augmenter sa valeur nice (rĂ©duire sa prioritĂ©)
  • Seul root peut diminuer la valeur nice (augmenter la prioritĂ©)
  • On ne peut pas revenir Ă  une valeur plus basse sans droits root

Cas d'usage réels :

  • Compilation : nice -n 15 make (ne pas ralentir le systĂšme)
  • Sauvegarde : nice -n 10 rsync ... (basse prioritĂ©)
  • Serveur critique : sudo renice -10 -p PID_serveur (haute prioritĂ©)

9Processus démon

Q25. Caractéristique d'un processus démon dans la colonne TTY

Qu'est-ce qui caractérise un processus démon dans la colonne TTY ?

Correction

Commande pour lister les démons :

$ ps aux | grep -E '^\w+\s+\d+.*\?'
# ou plus simple
$ ps aux | grep ' ?'
Réponse : Un processus démon a un ? (point d'interrogation) dans la colonne TTY.

Signification :

  • Le ? indique que le processus n'est pas attachĂ© Ă  un terminal
  • Les dĂ©mons tournent en arriĂšre-plan sans interaction utilisateur
  • Ils dĂ©marrent gĂ©nĂ©ralement au boot du systĂšme
  • Exemples : serveurs web, bases de donnĂ©es, services systĂšme

Exemple de sortie :

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.1  0.4 168844 9256 ?        Ss   08:15   0:02 /sbin/init
root       385  0.0  0.2  29008  5284 ?        Ss   08:15   0:00 /lib/systemd/systemd-journald
root       425  0.0  0.1  20644  3156 ?        Ss   08:15   0:00 /lib/systemd/systemd-udevd
message+   632  0.0  0.1   7352  3524 ?        Ss   08:15   0:00 /usr/bin/dbus-daemon
Comparaison TTY :
  • pts/0, pts/1, tty1 : Processus attachĂ©s Ă  un terminal (interactifs)
  • ? : Processus dĂ©mons (non interactifs)
Q26. Services actifs sur le Raspberry Pi

Citez 3 services actifs et expliquez leur rĂŽle.

Correction

Commande pour lister les services :

$ systemctl list-units --type=service --state=active

Pour voir les détails d'un service :

$ systemctl status nom_service

Exemples de services courants :

1. ssh.service (sshd)

$ systemctl status ssh

RÎle : Serveur SSH (Secure Shell) qui permet les connexions à distance sécurisées au Raspberry Pi. C'est grùce à ce service que vous pouvez vous connecter avec ssh depuis un autre ordinateur.

  • Port par dĂ©faut : 22
  • Configuration : /etc/ssh/sshd_config
  • Essentiel pour l'administration Ă  distance

2. systemd-journald.service

$ systemctl status systemd-journald

RÎle : Service de journalisation systÚme qui collecte et stocke les logs de tous les services et du noyau. Il permet de consulter l'historique des événements systÚme.

  • Commande pour voir les logs : journalctl
  • Logs stockĂ©s en binaire (plus efficace)
  • Permet le dĂ©pannage et le diagnostic

3. cron.service

$ systemctl status cron

RÎle : Planificateur de tùches qui exécute des commandes ou scripts à des moments programmés (toutes les heures, tous les jours, etc.).

  • Configuration : crontab -e
  • UtilisĂ© pour les sauvegardes automatiques, mises Ă  jour, etc.
  • Format : minute heure jour mois jour_semaine commande

Autres services importants :

  • networking.service : Gestion des interfaces rĂ©seau
  • systemd-timesyncd.service : Synchronisation de l'heure via NTP
  • bluetooth.service : Gestion du Bluetooth
  • avahi-daemon.service : DĂ©couverte de services rĂ©seau (mDNS)
  • dbus.service : Bus de messages inter-processus

Commandes utiles pour gérer les services :

# Démarrer un service
$ sudo systemctl start nom_service

# ArrĂȘter un service
$ sudo systemctl stop nom_service

# Redémarrer un service
$ sudo systemctl restart nom_service

# Activer au démarrage
$ sudo systemctl enable nom_service

# Désactiver au démarrage
$ sudo systemctl disable nom_service

# Vérifier si un service est actif
$ systemctl is-active nom_service

# Voir les logs d'un service
$ journalctl -u nom_service -f
Hiérarchie des processus démons :
Tous les démons sont généralement des enfants (directs ou indirects) du processus systemd (PID 1) sur les systÚmes modernes, ou init sur les anciens systÚmes.