6 - Les processus

Les processus

Chaque application, chaque commande est un processus.

Certains processus vont s’exécuter jusqu’à ce que vous les arrêtiez, d’autres vont réaliser une tâche et s’arrêter tout seul.

Exemple:

  • La commande ls : elle s’exécute et se termine tout de suite. Vous pouvez taper une autre commande.

  • La commande firefox : elle ouvre Firefox mais reste en exécution jusqu’à ce que vous fermiez Firefox. Notez que vous ne pouvez plus utiliser votre terminal tant que Firefox fonctionne.

Comment faire pour lancer Firefox et pouvoir continuer à utiliser le terminal?

Quand une commande vous empêche d’utiliser le terminal pendant son exécution, c’est parce qu’elle s’exécute au premier plan.

Comment faire pour qu’une application s’exécute en arrière plan?

Deux possibilités:

  • Lors de l’exécution initiale: lancez la commande suivi de &:
$ firefox &
  • Si la commande s’exécute déjà et que vous souhaitez la passer en arrière plan, vous devez d’abord faire Ctrl-z pour stopper l’application. Notez alors que vous pouvez utiliser votre terminal mais le programme, lui n’est plus utilisable. Tapez ensuite bg (pour background), le programme va alors s’exécuter en arrière plan.

  • Comment faire pour remettre la commande au premier plan? Avec fg (pour foreground).


Exercices 1

Lancez Firefox puis faites le passer en arrière plan et ramenez le au premier plan.

Pour arrêter une commande au premier plan: Ctrl-c


Tout d’abord, la commande permettant d’afficher les processus:

$ ps -f

Si vous entrez cette commande, vous voyez que les processus sont identifiés par deux numéros: pid et ppid:

  • pid: identifiant du processus

  • ppid: identifiant du processus père

Le processus père est le processus qui les a créé.

Exemple:

Si vous lancez une commande depuis votre terminal, celui-ci sera le père de la commande que vous venez de lancer.


Exercices 2

Avec ps, notez le pid de votre shell. Lancez Firefox. Quel est le pid de Firefox? Quel est le pid du père de Firefox?


Que se passe-t-il si on tue le père d’un processus?

Il sera adopté par le processus 1.

Comment se nomme le processus 1?

Il est donc possible de créer un arbre généalogique avec tous les processus.

L’arborescence des processus s’obtient avec:

$ pstree

Exercices 3

Lancez Firefox en tâche de fond à l’aide de la ligne de commande, notez son pid et son ppid (le ppid devrait être votre SHELL).

Fermez le terminal puis ouvrez-en un nouveau.

Quel est le ppid de Firefox maintenant?


Un processus peut être dans plusieurs états:

  • Élu: c’est lui qui est sur le processeur, en cours d’exécution.

  • Prêt: il est dans la file d’attente du processeur, il n’est en attente d’aucune ressource.

  • Bloqué: il est en attente d’une ressource autre que le processeur (disque par exemple).

  • Zombie: le processus est mort mais son père n’a pas encore pris en compte sa mort. Il y a toujours une entrée le concernant dans la table des processus.

Ces différents états sont gérés par l’ordonnanceur.

Pour afficher les processus et leur utilisation des ressources:

$ top

À quelle fréquence se rafraîchit top? Comment obtenir un rafraîchissement toutes les secondes?

L’autre commande que nous avons vu est ps.

Pour arrêter des processus:

$ kill pid

kill peut avoir différents paramètres. Pour tuer un processus immédiatement:

$ kill -9 pid

killall peut détruire tous les processus ayant le même nom:

$ killall httpd

Il est aussi possible d’attendre la fin d’une commande avant d’en exécuter une autre même si celle-ci a été lancée en arrière plan.

Exemple:

$ firefox &
wait $!

Ou encore, dans un script:

firefox &
wait $!
echo "Fin du script"

Si vous exécutez un processus à partir du terminal, la fermeture du terminal entraine la fin du processus.

Pour éviter ce comportement, deux possibilités existent:

Une fois le processus démarré:

$ disown <pid>

Au lancement de la commande:

$ nohup <commande>

Exercice 4

  1. Lancez la commande
$ gedit
  • Notez que cette commande s’exécute tant que vous ne fermez pas le fenêtre.

  • Ouvrez un autre terminal, trouvez le pid de la commande gedit et tuez la commande.

  1. Ouvrez un terminal, exécutez Firefox en tâche de fond. Fermez le terminal. Que se passe-t-il avec Firefox?
  • Essayez maintenant la même opération mais après avoir exécuté
$ disown  
  • Et après avoir lancé Firefox de cette façon:
$ nohup firefox

Codes de retour

Une commande peut s’exécuter correctement mais peut aussi se terminer avec une erreur.

Chaque commande va donc avoir une valeur de retour qui permet de savoir s’il y a eu une erreur ou non.

Par convention, si la valeur de retour de la commande est 0, la commande s’est exécutée correctement sans erreur.

S’il y a des erreurs, la valeur de retour sera différente de 0.

Variables prépositionnées

Certaines variables sont réservées par le système pour des significations particulières.

Il sera ainsi possible de connaitre la valeur de retour de la dernière commande:

$ echo $?

Ou de connaitre le PID de la dernière commande lancée en tâche de fond:

$ echo $!

Exercices 5

  1. Lancez la commande ls. Quel est son code de retour? Est-ce un succès ou un échec?

  2. Sans être root, lancez la commande $ find / -name “*.conf”. Quel est son code de retour? Pourquoi?


Combinaison de commandes

Il est possible de combiner des commandes. Nous avons déjà vu le | mais il y a d’autres possibilités.

$ Commande 1 ; Commande 2 ; …

Permet d’enchainer les commandes les unes après les autres.

$ Commande 1 && Commande 2

Exécutera Commande 2 seulement si Commande 1 s’est exécutée avec succès et n’a pas renvoyé d’erreur.

$ Commande 1 || Commande 2

Exécutera Commande 2 seulement si Commande 1 a eu un problème et a renvoyé une erreur.

Exemples:

Tester l’existence d’un fichier et exécuter la commande le cas échéant:

$ test -e fichier && commande

Afficher un message OK si la commande a réussi:

$ commande && echo OK

Ou bien afficher un message d’erreur si la commande .choue:

$ commande || echo ERREUR

Et enfin, afficher OK si le code de retour est 0 ou ERREUR si le code de retour est différent de 0 :

$ Commande 1 && echo OK || echo ERREUR

Exemple :

$ test $var -eq 0 && echo "$var = 0" || echo "$var != 0"

La commande s’exécute en tâche de fond (arrière plan), vous récupérez la main.

$ Commande 1 &

Les commandes s’exécutent de façon asynchrone, totalement indépendamment l’une de l’autre.

$ Commande 1 & Commande 2

Exercices 6

  1. Exécutez:
$ find / -name "*.conf" && ls
  • Est-ce que les deux commandes s’exécitent? Et si vous les inversez?
  1. Exécutez
$ find / -name "*.conf" || ls
  • Est-ce que les deux commandes s’exécutent? Et si vous les inversez?
  1. Exécutez
$ find / -name "*.conf" & ls
  • Est-ce que les deux commandes s’exécutent? Et si vous les inversez?

Il est possible d’utiliser des () pour déterminer la priorité des opérateurs &, &&, |, || et ;

Exemple:

ls est exécutée s’il y a une erreur avec find et le résultat de la ou des commande(s) exécutée(s) sera filtré par grep:

$ (find / -name "*.conf" 2>/dev/null || ls) | grep a

ls sera exécuté s’il y a une erreur avec find et le résultat de ls seulement sera filtré par grep:

$ find / -name "*.conf" 2>/dev/null || (ls | grep a)

Rappel:

$ $(commande) 

permet de stocker le résultat d’une commande dans une variable.

Exemple:

La commande suivante permet de stocker le résultat de la commande find dans la variable var.

$ var=$(find / -name "*.conf")
$ echo $var

Cette enchainement donne le même affichage que mais le résultat est réutilisable:

$ find / -name "*.conf"

Commandes utiles

Pour chercher dans le contenu de plusieurs fichiers :

$ egrep <chaine> <fichiers>
$ egrep ssh *

Pour connaître l’espace disque:

$ df [-h]

Pour connaître la taille d’un fichier ou d’un répertoire:

$ du [-sh] répertoire

Pour connaître l’état de la mémoire:

$ free