Linux sans magie #20 — Premier plan, arrière-plan et jobs : comprendre &, jobs, fg et bg

Comprendre le job control dans Bash : lancer une commande en arrière-plan, lister les jobs, suspendre un programme et le reprendre avec fg ou bg.

Dans les articles précédents, nous avons vu comment identifier des processus, gérer des services avec systemctl et lire leurs logs avec journalctl. Il reste pourtant un comportement très quotidien du terminal qui peut sembler étrange au début : une commande peut occuper le terminal, être envoyée en arrière-plan, être suspendue, puis revenir au premier plan.

Bash appelle cela le job control.

L’objectif de cet article est de comprendre ce que représentent les jobs du shell et d’utiliser correctement &, jobs, fg, bg et Ctrl+Z, sans les confondre avec une liste générale des processus du système.

Contexte et problème

Lancez par exemple :

sleep 300

Le terminal semble alors « bloqué ». En réalité, il ne l’est pas : Bash attend simplement la fin du programme placé au premier plan.

Pendant ce temps, vous ne retrouvez pas l’invite du shell pour saisir une autre commande dans ce même terminal.

Il existe plusieurs façons de gérer cette situation. On peut notamment :

  • démarrer directement une commande en arrière-plan ;
  • suspendre une commande qui tourne au premier plan ;
  • reprendre un job suspendu en arrière-plan ;
  • ramener un job au premier plan ;
  • afficher les jobs que le shell courant connaît.

Ces opérations relèvent du shell. Elles ne remplacent ni ps, ni les outils de supervision des processus.

Concept ou architecture

Processus et job ne désignent pas exactement la même chose

Un processus est une entité gérée par le noyau Linux et possède notamment un PID.

Un job, dans Bash, est une construction du shell utilisée pour suivre une commande ou un pipeline lancé depuis ce shell lorsque le job control est actif.

Le shell attribue à ses jobs des identifiants comme :

[1]
[2]

Dans les commandes de job control, on référence généralement ces jobs avec une notation appelée jobspec :

%1
%2

Ce numéro de job n’est pas un PID.

La commande :

jobs -l

permet justement d’afficher les jobs en incluant des PID, ce qui aide à voir la différence entre les deux notions.

Premier plan

Une commande au premier plan contrôle le terminal pendant son exécution. Bash attend sa fin ou un changement d’état avant de rendre l’invite.

Exemple :

sleep 300

Tant que sleep reste au premier plan, le shell n’affiche pas de nouvelle invite dans ce terminal.

Arrière-plan avec &

Pour demander à Bash de lancer une commande en arrière-plan, on ajoute & à la fin :

sleep 300 &

Bash rend alors immédiatement la main et affiche généralement un numéro de job ainsi qu’un identifiant de processus.

Le programme continue à s’exécuter, mais l’invite du shell redevient disponible.

Cela ne signifie pas que la commande est devenue un service, ni qu’elle est indépendante du shell ou de la session. & signifie seulement qu’elle est lancée en arrière-plan dans le contexte du job control du shell.

jobs : voir les jobs du shell courant

La commande :

jobs

affiche les jobs actifs connus du Bash courant.

Exemple de présentation possible :

[1]+  Running                 sleep 300 &

Le rendu exact dépend de l’état du job et de la version du shell.

Pour afficher aussi les PID :

jobs -l

Le point important est la portée de la commande : jobs ne parcourt pas tous les processus de la machine.

Si vous ouvrez un second terminal et exécutez jobs, il ne retrouvera normalement pas les jobs créés dans le premier Bash. Chaque shell maintient sa propre table de jobs.

Pour rechercher des processus au niveau du système, utilisez plutôt des commandes comme :

ps

ou les méthodes vues dans l’article consacré aux processus et PID.

Suspendre avec Ctrl+Z

Supposons qu’une commande tourne déjà au premier plan :

sleep 300

Vous pouvez utiliser :

Ctrl+Z

Le terminal envoie alors l’action de suspension via le mécanisme de contrôle du terminal, et Bash reprend la main lorsque le job est arrêté.

Vous pouvez ensuite vérifier son état :

jobs

Vous verrez un état du type :

[1]+  Stopped                 sleep 300

Le programme n’est pas terminé : il est suspendu.

Il faut distinguer cette action de Ctrl+C. Dans un terminal interactif standard, Ctrl+C provoque normalement l’envoi de SIGINT au job au premier plan afin de demander son interruption. Ctrl+Z, lui, provoque normalement une suspension avec le mécanisme associé à SIGTSTP.

Autrement dit :

Ctrl+C → demander l'interruption
Ctrl+Z → suspendre le job

Reprendre un job avec bg

Un job suspendu peut être repris en arrière-plan avec :

bg %1

Ici %1 désigne le job numéro 1 dans la table de jobs du shell.

Après cette commande, vérifiez :

jobs

Le job doit apparaître comme actif, généralement avec un état Running.

Si aucun jobspec n’est fourni, Bash peut utiliser son notion de job courant. Pour rester explicite dans un lab ou une procédure, utiliser %1, %2, etc. évite les ambiguïtés lorsque plusieurs jobs existent.

Ramener un job au premier plan avec fg

Pour reprendre le job 1 au premier plan :

fg %1

Le job reprend alors le contrôle du terminal et Bash attend de nouveau sa fin ou un changement d’état.

Si vous exécutez ensuite Ctrl+C, vous pouvez interrompre le sleep du lab et récupérer l’invite.

La commande fg sert donc à faire revenir dans le terminal actif un job qui était suspendu ou exécuté en arrière-plan.

Comprendre %1, %2, %+ et %-

Bash appelle jobspec la notation utilisée pour désigner un job.

Les formes les plus utiles pour commencer sont :

%1  → job numéro 1
%2  → job numéro 2
%+  → job courant
%-  → job précédent

Dans la sortie de jobs, le job courant est généralement marqué par + et le précédent par -.

Pour une première utilisation, les numéros explicites %1 et %2 sont souvent plus simples à suivre.

Prérequis

Le lab nécessite :

  • une session Bash interactive ;
  • le job control actif ;
  • la commande sleep, présente sur les environnements Linux courants.

Vérifiez le shell courant :

echo "$BASH_VERSION"

Puis vérifiez que sleep est disponible :

command -v sleep

Dans un script Bash non interactif, le comportement du job control n’est pas le même et il peut être désactivé. Cet article traite volontairement le cas du terminal interactif.

Mise en pratique

1. Lancer une commande directement en arrière-plan

Exécutez :

sleep 300 &

Bash doit rendre immédiatement l’invite.

Affichez la table des jobs :

jobs

Puis :

jobs -l

Résultat attendu

Vous devez voir au moins un job en cours d’exécution. Avec jobs -l, un PID doit également apparaître.

Retenez les deux identifiants :

numéro de job → utilisé par fg/bg avec %N
PID           → identifiant du processus au niveau système

2. Ramener le job au premier plan

Si le job est numéro 1 :

fg %1

Le prompt disparaît tant que sleep reste au premier plan.

3. Suspendre le job

Appuyez sur :

Ctrl+Z

Puis :

jobs

Le job doit apparaître comme suspendu ou Stopped.

4. Le reprendre en arrière-plan

Exécutez :

bg %1

Puis vérifiez :

jobs

Le job doit de nouveau apparaître en cours d’exécution.

5. Le ramener une dernière fois au premier plan

fg %1

Terminez le lab avec :

Ctrl+C

Puis vérifiez :

jobs

Une fois que Bash a pris en compte la fin du job, il ne doit plus apparaître dans la table des jobs actifs.

Vérification

Le lab est réussi si vous êtes capable de décrire cette séquence :

sleep 300 &
      ↓
job lancé en arrière-plan
      ↓
fg %1
      ↓
job au premier plan
      ↓
Ctrl+Z
      ↓
job suspendu
      ↓
bg %1
      ↓
job repris en arrière-plan
      ↓
fg %1 puis Ctrl+C
      ↓
job interrompu et lab terminé

Bonnes pratiques

Utilisez jobs avant fg ou bg lorsque plusieurs jobs existent :

jobs -l

Cela évite de manipuler le mauvais job.

Préférez des jobspecs explicites dans une procédure :

fg %2
bg %1

Ne supposez pas qu’un numéro de job reste valable longtemps. Lorsque des jobs se terminent et que la table évolue, les numéros disponibles peuvent changer lors de sessions ultérieures.

Enfin, ne transformez pas & en solution universelle pour faire tourner une application durablement. Pour un service système ou une application qui doit être supervisée, redémarrée et gérée au boot, un gestionnaire de services comme systemd est généralement plus approprié.

Sécurité

Le job control ne donne aucun privilège supplémentaire. Une commande lancée avec &, fg ou bg conserve les droits du processus et de l’utilisateur qui l’a lancée.

Le risque principal est opérationnel : envoyer en arrière-plan une commande ayant des effets importants ne réduit pas ces effets. Une suppression, une copie massive, une opération réseau ou une modification de configuration reste potentiellement dangereuse, qu’elle soit visible au premier plan ou non.

Dans un environnement sensible, vérifiez toujours la commande avant de la lancer en arrière-plan et contrôlez son état au lieu de considérer qu’un retour immédiat du prompt signifie que l’opération est terminée.

Coûts

Le lab n’utilise aucune ressource payante particulière. Il s’exécute avec des commandes locales très légères.

Sur une machine facturée à l’usage, une commande réelle exécutée longtemps en arrière-plan peut évidemment continuer à consommer CPU, mémoire, stockage ou trafic réseau. Le caractère « arrière-plan » ne supprime pas le coût de la charge de travail.

Limites et points de vigilance

Cet article couvre le job control interactif de Bash. Il ne traite pas en profondeur :

  • nohup ;
  • disown ;
  • la survie d’un processus après fermeture du terminal ;
  • les sessions et groupes de processus en détail ;
  • le controlling terminal ;
  • les multiplexeurs de terminal comme tmux ou screen ;
  • les différences de job control entre shells.

Le comportement décrit suppose également que le job control est actif. Dans des contextes non interactifs ou des scripts, les hypothèses de cet article ne doivent pas être transposées automatiquement.

Enfin, un programme peut traiter ou ignorer certains signaux selon sa propre logique. Les raccourcis clavier décrits ici correspondent au comportement habituel d’un terminal interactif, mais ils ne constituent pas une garantie que toute application réagira de la même façon.

Rollback ou nettoyage

Le lab ne crée aucun fichier ni service permanent.

Si un sleep reste actif dans la table de jobs, ramenez-le au premier plan :

fg %1

puis utilisez :

Ctrl+C

Si plusieurs jobs existent, commencez par :

jobs -l

et identifiez précisément celui du lab avant d’agir.

Références officielles

Conclusion

Le job control devient beaucoup plus simple dès que l’on sépare deux niveaux : Linux gère les processus et leurs PID, tandis que Bash maintient une table de jobs pour les commandes lancées depuis le shell interactif.

& lance en arrière-plan, jobs montre ce que le shell suit, Ctrl+Z suspend, bg reprend en arrière-plan et fg ramène au premier plan.

Ce mécanisme est utile pour piloter ponctuellement des commandes dans un terminal. Il ne remplace ni la gestion des processus à l’échelle du système, ni un véritable gestionnaire de services.