Séance 4 : Processus

Processus

On appelle processus l'exécution d'un programme.

Sous Linux, chaque processus est identifié par un numéro appelé PID (Processus IDentifier).

À chaque processus est également associé :

  • l'identifiant de l'utilisateur pour le compte duquel il s'exécute (UID), qui détermine les droits du processus ;

  • l'identifiant de son processus parent (PPID).

ps [options] — processes

Affiche la liste des processus en cours (par défaut : uniquement ceux de l'utilisateur et du terminal courant).

-u

Affiche tous les processus de l'utilisateur (tous terminaux confondus).

-A

Affiche tous les processus du système.

-f

Donne plus d'information sur les processus affichés.

-H

Ordonne et indente les processus selon leur généalogie (PPID).

top

Affiche les processus consommant le plus de ressource CPU, en rafraichissant l'affichage régulièrement.

Pour quitter top, tapez q ou CTRL+C.

kill <pid> [...]

Arrête (« tue ») le(s) processus identifié(s) par pid.

Note

On verra plus tard une utilisation plus générale de la commande kill.

Processus suspendus

  • Un processus peut être suspendu en tapant CTRL+Z pendant son exécution.

  • Le shell reprend immédiatement la main.

  • Le processus est « endormi », mais toujours « vivant » : son exécution peut être reprise.

jobs

Affiche la liste des processus suspendus ou en tâche de fond pour le shell courant.

Chaque process est identifié par un numéro de job (différent de son PID).

-l

Affiche également le PID de chaque processus.

-p

Affiche uniquement le PID des processus.

Note

Les numéros de job sont propres au shell, alors que les PIDs sont valables pour tout le SE.

fg [jobid] — foreground

Relance au premier plan le job spécifié.

jobid

Le numéro de job du processus à relancer.

Par défaut : le processus exécuté le plus récemment.

kill %<jobid>

Au lieu d'un PID, la commande kill accepte aussi comme argument un numéro de job, précédé du caractère pourcent %.

Tâches de fond

  • À chaque ligne de commande, le shell lance un processus (ou plusieurs, dans le cas des pipelines), et attend qu'il(s) se termine(nt) pour reprendre la main.

  • Il est également possible lancer un processus en tâche de fond ; dans ce cas, le shell n'attend pas la fin du processus et reprends la main immédiatement.

  • Ceci peut être intéressant pour des tâches longues (compilation, téléchargement de fichier, décompression d'archive...)

Avertissement

Lorsqu'une tâche de fond affiche du texte, ceci peut avoir des effets inattendus.

Lancer directement un processus en tâche de fond

On ajoute à la fin de la ligne de commande le caractère esperluette (&).

Exemple :

curl http://example.org/ubuntu-19-10.iso >ubuntu &

NB: le & peut également être utilisé comme un séparateur pour lancer plusieurs processus sur la même ligne de commande :

prog1 & prog2 & prog3
# lance prog1 et prog2 et tâche de fond, et prog3 au premier plan

bg [jobid] — background

Relance en tâche de fond un processus suspendu.

jobid

Le numéro de job du processus à relancer.

Par défaut : le processus exécuté le plus récemment.

Signaux

  • Un signal est un message envoyé par le SE à un processus.

  • La plupart des signaux ont pour effet de tuer le processus, mais

    • certains ont un autre effet (voir ci-après), et

    • un programme peut personnaliser sa répose à certains signaux.

kill [options] <pid> [...]

Envoie un signal à un ou plusieurs processus.

pid [...]

Le(s) PID(s) du/des processus à qui envoyer le signal.

-s [signal]

Le signal à envoter (par défaut SIGTERM).

Quelques signaux utiles

  • SIGTERM : demande « poliment » au processus de s'arrêter

  • SIGKILL : tue le processus (utile lorsque SIGTERM échoue, ce signal n'est pas « personnalisable »)

  • SIGTSTP : suspend le processus

  • SIGCONT : relance un processus suspendu

Remarques

  • CTRL+C a pour effet d'envoyer un signal (SIGINT) au(x) processus courant(s).

  • CTRL+Z a pour effet d'envoyer le signal SIGTSTP au processus courant.

  • bg sert en fait à envoyer SIGCONT à un processus.

  • fg envoie également SIGCONT au processus, et fait en sorte d'attendre la fin.

  • On peut voir que man a personnalisé sa réponse à SIGINT (le procecuss n'est pas tué lorsqu'on tape CTRL+C).

Enchaînement

On a déjà vu plusieurs moyens de lancer plusieurs processus depuis une seule ligne de commande :

# en parallèle
prog1 & prog2 & prog3

# en parallèle avec redirections via des tubes
prog1 | prog2 | prog3

Enchaînement séquentiel

On peut également lancer plusieurs processus l'un à la suite des autres, en les séparant par un point-virgule (;) :

# en séquence
prog1 ; prog2 ; prog3

Indication

Le point-virgule joue exactement le même rôle que le retour à la ligne.

Valeur de retour d'un processus

int main(int argc, char* argv[]) {
  /* ... */
}
  • La valeur de retour de main est récupérée par le SE; on l'appelle parfois code de statut (status code).

  • Par convention, elle indique le succès (0) ou l'échec (≠0) du processus.

  • La commande echo $? affiche le code de status de la dernière commande exécutée.

Enchaînements conditionnels

  • « et alors » && : la commande de droite est exécutée si et seulement si la commande de gauche a réussi (status = 0) :

    prog1 && prog2
    
  • « ou sinon » || : la commande de droite est exécutée si et seulement si la commande de gauche a échoué (status ≠ 0) :

    prog1 || prog2
    
  • dans tous les cas, le code de statut de l'enchaînement est celui de la dernière commande exécutée.

Priorité et parenthèses

  • Le connecteur pipe (|) a priorité sur les connecteurs d'enchaînement.

  • On peut influer sur les priorités avec des parenthèses :

    $ echo Z; echo A | sort
    Z
    A
    
    $ (echo Z; echo A) | sort
    A
    Z
    

Travaux dirigés

Échauffement

  1. À l'aide de la commande echo, affichez Bonjour le (beau) monde.

  2. À l'aide de la commande echo, affichez un point-virgule (;).

  3. À l'aide de la commande echo, affichez une esperluette (&).

  4. À l'aide de la commande echo, affichez deux esperluettes (&&).

Exercice 1

On rappelle que par défaut, ps n'affiche que les processus de l'utilisateur et du terminal courant.

  1. Ouvrez un terminal.

  2. Combien de processus devrait afficher la commande ps ? Faites le test et expliquez, le cas échéant, la différence avec votre prédiction. Vous pouvez vous aider des options -f ou -H.

  3. Affichez la mage man de la commande ps, puis suspendez le processus.

  4. Combien de processus devrait maintenant afficher la commande ps ? Faites le test et expliquez, le cas échéant, la différence avec votre prédiction.

  5. Combien de processus devrait afficher la commande job ? Faites le test et expliquez, le cas échéant, la différence avec votre prédiction.

  6. Lancez la commande jobs -l pour voir le PID du/des job(s). Ceci est-il cohérent avec la sortie de la commande ps.

  7. Arrêtez le processus man.

  8. Vérifiez avec ps et jobs que le processus est bien arrêté.

Exercice 2

  1. Affichez tous les processus qui s'exécutent en votre nom.

  2. Affichez tous les processus du système.

  3. À l'aide de la commande wc, affichez le nombre total de processus.

  4. À l'aide de la commande egrep, affichez le nombre de processus dont le nom contient gsd.

  5. À l'aide de la commande cut, affichez les PIDs des processus dont le nom contient gsd.

Exercice 3

  1. Ouvrez la commande man ps, puis suspendez le processus.

  2. Dans le même terminal, ouvrez la commande man top, puis suspendez le processus.

  3. Reprenez la lecture de la page man de top.

  4. Suspendez le processus, puis reprenez la lecture de la page man de ps.

  5. Suspendez le processus, puis reprenez la lecture de la page man de top.

  6. Quittez définitivement la lecture de cette page.

  7. De retour au shell, arrêtez le processus man ps sans le réactiver.

  8. Vérifiez que les deux processus ont bien été arrêtés.

Exercice 4

  1. Copiez le fichier /dev/random dans le répertoire courant.

  2. Si la copie n'est pas terminée au bout de 5 secondes, suspendez le processus et relancez le en tâche de fond.

  3. Affichez la taille du fichier copié à avec ls -l.

  4. Patientez quelques secondes, puis vérifiez si le processus cp est toujours en cours.

  5. Si c'est le cas, affichez à nouveau la taille du fichier.

  6. Ça n'était pas une bonne idée... Interompez le processus cp et supprimez la copie.

Note

Le fichier /dev/random est un fichier virtuel, au même titre que /dev/null. Lorsqu'on lit son contenu, ce fichier produit des données aléatoire, sans jamais s'arrêter.

Interlude : substitution

En plaçant une (ligne de) commande entre guillemets inversés (`, AltGr+7 sur un clavier PC AZERTY), on peut récupérer sa sortie standard pour la réinjecter la ligne de commande extérieure :

# crée une copie "datée" du fichier /etc/passwd
cp /etc/passwd passwd-`date +%Y-%m-%d-%H:%M:%S`
  • Si la sortie standard contient des espaces (y compris des sauts de ligne), la substitution générera plusieurs arguments.

Exercice 5

  1. Ouvrez la commande man ps, puis suspendez le processus.

  2. Ouvrez la commande man top, puis suspendez le processus.

  3. Ouvrez la commande man kill, puis suspendez le processus.

  4. Ouvrez la commande man ls, puis suspendez le processus.

  5. Affichez la liste des PIDs des processus suspendus à l'aide de la commande jobs.

  6. À l'aide d'une substitution, tuez tous les processus suspendus en une seule commande.

  7. Si cela ne fonctionne pas, utilisez le signal SIGKILL au lieu du signal par défaut (SIGTERM).

Commande utile : wget [options] <url>

Télécharge dans un fichier le contenu de l'URL passée en paramètre.

Le nom du fichier correspond à la dernière partie de l'URL.

Le code de statut est différent de 0 en cas d'erreur de téléchargement.

-q, --quiet

N'affiche aucune information pendant le téléchargement.

Exercice 6

  1. Créez un répertoire vide, et rendez-vous dans ce répertoire.

  2. Lancez la ligne de commande suivante :

    wget -q https://httpbin.org/delay/15 & wget -q https://httpbin.org/delay/5 & wget -q https://httpbin.org/delay/10 &
    

    Cette ligne de commande va télécharger en silence (-q) en parallèle (&) les 3 URLs dans trois fichiers nommés respectivement 15, 5 et 10.

  3. Utilisez répétitivement la commande ls pour voir apparaître les fichiers téléchargés. Apparaissent-t-ils dans l'ordre de la ligne de commande ? Cela confirme-t-il que les 3 commandes se sont exécutées en parallèle ?

  4. Téléchargez maintenant au premier plan le contenu de l'URL https://httpbin.org/delay/1?foo=bar (sans utiliser l'option -q de wget). Quel fichier a été créé ?

  5. Téléchargez maintenant au premier plan le contenu de l'URL https://httpbin.org/delay/2?foo=bar&toto=tata (sans utiliser l'option -q de wget). Quel(s) fichier(s) a/ont été créé(s) ? Tout s'est-il bien passé ? Avez-vous bien pris toutes les précautions nécessaires ?

Complément d'information : egrep [options] <regex>

egrep retourne 0 si regex est trouvée, 1 sinon.

-q, --quiet, --silent

N'affiche pas les lignes ou regex est trouvée.

Avec cette option, seul le code de retour est utile. Par conséquent, egrep s'arrête à la première correspondance.

Exercice 7

  1. À l'aide de la commande egrep, affichez toutes les lignes du fichier /var/log/syslog qui contiennent le mot kernel.

  2. Écrivez une ligne de commande qui affiche OUI si le fichier /var/log/syslog contient le mot gnome, et NON sinon.

  3. Écrivez une ligne de commande qui affiche OUI si le fichier /var/log/syslog contient le mot lutin, et NON sinon.