temps de lecture : 10 minutes

Vous lancez ./gradlew build, le terminal est bloqué pendant 3 minutes, et vous avez besoin de faire autre chose en attendant ? Pas besoin d’ouvrir un nouvel onglet. Ctrl+Z suspend le processus, fg le ramène exactement là où vous l’avez laissé. C’est le tips Unix le plus sous-estimé du quotidien d’un développeur.

1. Le problème : un terminal occupé

Tout développeur a connu cette situation :

$ ./gradlew build
> Building...

Le terminal est bloqué. Vous ne pouvez plus taper aucune commande. Et vous avez besoin de consulter un fichier, lancer un git status, ou vérifier un port occupé.

terminal bloque

La plupart des développeurs ouvrent un nouveau terminal. Mais il existe une solution plus élégante, plus rapide, et native : la gestion des jobs.

2. Les trois commandes indispensables

2.1. Ctrl+Z — Suspendre (SIGTSTP)

Ctrl+Z envoie le signal SIGTSTP au processus en avant-plan. Le processus est suspendu — pas tué — et le terminal retrouve son prompt.

$ ./gradlew build
> Building...
^Z
[1]+  Stoppé    ./gradlew build
$

Le nombre entre crochets [1] est le numéro de job. Le + indique le job par défaut.

2.2. fg — Reprendre en avant-plan

fg ramène le job suspendu au premier plan. Le processus reprend exactement là où il s’était arrêté.

$ fg
./gradlew build
> Building... (reprend où il en était)

Avec un numéro de job spécifique :

$ fg %2

2.3. bg — Reprendre en arrière-plan

bg reprend le processus sans bloquer le terminal. Idéal pour les longs builds.

$ bg
[1]+ ./gradlew build &
$

Le & à la fin signifie que le processus tourne en arrière-plan.

2.4. jobs — Lister les jobs du shell

$ jobs
[1]-  Stoppé    vim README.md
[2]+  En cours   ./gradlew build
jobs lifecycle

3. Scénario 1 : Le long build

C’est le cas d’usage le plus courant. Vous lancez un build Gradle, le terminal est bloqué, et vous avez besoin de faire autre chose.

scenario build

3.1. Pas à pas

$ ./gradlew build
> Building...
^Z
[1]+  Stoppé    ./gradlew build

$ git status
On branch main
nothing to commit, working tree clean

$ fg
./gradlew build
> Building...
BUILD SUCCESSFUL in 2m 34s

4. Scénario 2 : L’éditeur oublié

Vous êtes dans vim, vous avez besoin de consulter un autre fichier sans quitter vim.

# Dans vim, en mode commande :
:shell
$ cat /path/to/other/file.txt
$ exit
# Retour dans vim

Mais c’est lourd. Avec Ctrl+Z, c’est immédiat :

# Dans vim, n'importe quel moment :
Ctrl+Z
[1]+  Stoppé    vim README.md

$ cat /path/to/other/file.txt
# ... lire le fichier ...

$ fg
vim README.md
# Retour exact là où on en était, curseur en place
vim suspend
vim restaure parfaitement son état après un fg : position du curseur, contenu du buffer, historique d’annulation — tout est préservé.

5. Scénario 3 : Le processus opencode suspendu

C’est le scénario qui a motivé cet article. Vous utilisez opencode (outil CLI pour piloter un LLM sur votre code), et le processus est suspendu.

opencode fg
$ opencode
# ... session en cours, LLM analyse le code ...
^Z
[1]+  Stoppé    opencode

$ git diff HEAD~1
# vérifier les changements récents

$ fg
opencode
# Le LLM reprend là où il s'était arrêté

L’avantage est double :

  1. Pas de perte de contexte : la session LLM, l’historique de conversation, les fichiers ouverts — tout est préservé

  2. Pas de redémarrage : pas besoin de relancer opencode, de recharger le contexte, de réexpliquer le problème au LLM

6. Scénario 4 : Gérer plusieurs jobs simultanément

fg et bg acceptent un numéro de job pour cibler un processus spécifique quand plusieurs sont suspendus.

$ vim config.yml
^Z
[1]+  Stoppé    vim config.yml

$ ./gradlew test
^Z
[2]+  Stoppé    ./gradlew test

$ htop
^Z
[3]+  Stoppé    htop

$ jobs
[1]   Stoppé    vim config.yml
[2]-  Stoppé    ./gradlew test
[3]+  Stoppé    htop

$ fg %2
./gradlew test
# Le build reprend en avant-plan

$ bg %3
[3] htop &
# htop reprend en arrière-plan
multiple jobs

6.1. Récapitulatif des commandes de jobs

Commande Effet Exemple

Ctrl+Z

Suspend le processus en avant-plan

Envoi de SIGTSTP

fg

Reprend le job par défaut en avant-plan

fg ou fg %1

fg %n

Reprend le job n en avant-plan

fg %2

bg

Reprend le job par défaut en arrière-plan

bg ou bg %1

bg %n

Reprend le job n en arrière-plan

bg %2

jobs

Liste les jobs du shell courant

jobs -l (avec PID)

kill %n

Termine le job n

kill %2

7. Différences entre fg, bg, Ctrl+Z, Ctrl+C et &

Beaucoup de développeurs confondent ces mécanismes. Voici une clarification décisive.

signals comparison
Raccourci/Commande Signal Effet Revenir en arrière ?

Ctrl+Z

SIGTSTP

Suspend le processus (figé, en mémoire)

Oui : fg ou bg

Ctrl+C

SIGINT

Tue le processus (terminé)

Non : processus détruit

Ctrl+\

SIGQUIT

Tue le processus + core dump

Non : processus détruit

commande &

Lance en arrière-plan directement

fg pour le ramener en avant-plan

Ctrl+Z est non-destructif. Le processus est figé tel quel, en mémoire. Vous pouvez reprendre immédiatement avec fg. C’est un pause, pas un stop.

8. Le cycle de vie complet d’un job

job lifecycle complete

9. Tips avancés

9.1. fg avec le job le plus récent et l’alternance

fg sans argument ramène le job marqué + (le plus récent). Mais vous pouvez aussi utiliser %- pour cibler le job précédent :

$ vim file1.txt
^Z
[1]+  Stoppé    vim file1.txt

$ vim file2.txt
^Z
[2]+  Stoppé    vim file2.txt

$ fg      # ramène job [2] (le plus récent)
$ fg %-   # ramène job [1] (le précédent)

9.2. tuer un job proprement

$ jobs
[1]-  Stoppé    vim config.yml
[2]+  Stoppé    ./gradlew test

$ kill %2       # envoie SIGTERM au job 2
$ kill -9 %1    # envoie SIGKILL au job 1 (force)

9.3. désown : détacher du shell

disown retire un job de la table des jobs du shell. Le processus continue de tourner mais ne peut plus être ramené avec fg :

$ ./gradlew build &
[1] 12345

$ disown %1
# Le processus continue mais n'est plus lié au shell
# Ça survives à la fermeture du terminal

9.4. Combiner avec nohup pour les longs processus

Pour qu’un processus survive à la fermeture du terminal :

$ nohup ./gradlew build &
[1] 12345
$ disown %1
# Le build continue même si vous fermez le terminal
advanced tips

10. Pièges et erreurs courantes

10.1. Confondre Ctrl+Z et Ctrl+C

C’est l’erreur la plus fréquente. Ctrl+C tue le processus. Ctrl+Z le suspend. Si vous appuyez sur Ctrl+C par réflexe, tout l’état est perdu — fichiers ouverts, sessions LLM, builds en cours.

ctrlz vs ctrlc

10.2. Les jobs sont locaux au shell

jobs, fg et bg ne fonctionnent que dans le shell qui a lancé les processus. Si vous ouvrez un nouveau terminal, vous ne verrez pas les jobs de l’autre.

# Terminal 1
$ vim file.txt
^Z
[1]+  Stoppé    vim file.txt

# Terminal 2 (nouveau)
$ jobs
# (rien — les jobs sont locaux au shell)

Pour voir les processus system-wide, utilisez ps ou htop :

ps aux | grep vim

10.3. Les jobs ne survivent pas à la fermeture du shell

Si vous fermez le terminal, tous les jobs suspendus ou en arrière-plan sont détruits. Pour qu’un processus survive, utilisez nohup + disown :

$ nohup ./gradlew build &
[1] 12345
$ disown %1
# Fermer le terminal → le build continue

10.4. Les processus interactifs et fg

Certains programmes interactifs ne se portent pas bien après un Ctrl+Z + fg. C’est rare mais ça arrive :

  • Certains programmes qui utilisent des signaux (vim, htop, less gèrent bien Ctrl+Z)

  • Les programmes réseau longs (ssh, opencode) récupèrent généralement correctement

  • Les programmes qui modifient le terminal (ncurses) peuvent parfois laisser le terminal dans un état inattendu

En cas de terminal corrompu après un fg, tapez :

reset

11. Diagramme récapitulatif

fg recap

12. Pourquoi fg est sous-estimé

La plupart des développeurs modernes découvrent fg tard, voire jamais. Quelques raisons :

  1. Les IDE cachent le terminal : VS Code propose un terminal intégré, mais les onglets multiples rendent fg moins nécessaire en apparence

  2. Les outils graphiques remplacent les CLI : les gestionnaires de fichiers, les moniteurs système, les clients Git graphiques

  3. tmux et screen : ces multiplexeurs résolvent le même problème différemment, mais fg est plus simple et toujours disponible

Pourtant, fg est :

  1. Universel : présent dans tous les shells POSIX (bash, zsh, fish…​)

  2. Sans dépendance : pas besoin d’installer tmux ou screen

  3. Instantané : deux frappes (Ctrl+Z puis fg) pour suspendre et reprendre

  4. Préservateur de contexte : l’état du processus est intact

why fg underrated

13. Mémoire technique : les signaux

Pour les curieux, voici les signaux impliqués :

Signal Nom Envoyé par Effet

2

SIGINT

Ctrl+C

Interruption — termine le processus

3

SIGQUIT

Ctrl+\

Quitte avec core dump

18

SIGTSTP

Ctrl+Z

Stop interactif — suspend le processus

19

SIGCONT

fg / bg

Continue — reprend un processus suspendu

15

SIGTERM

kill %n

Terminaison propre

9

SIGKILL

kill -9 %n

Terminaison forcée (impossible à intercepter)

Le flux complet :

signal flow

14. Conclusion

fg n’est pas un tips obscur — c’est un mécanisme fondamental du shell Unix, disponible depuis les années 70. Le fait que la plupart des développeurs l’ignorent est un symptôme de notre époque : les IDE et les multiplexeurs nous ont éloignés des bases.

Mais quand vous êtes sur un serveur SSH, dans un terminal minimal, ou simplement en train d’utiliser opencode et que le LLM est en plein travail — Ctrl+Z, fg, bg, jobs sont vos meilleurs amis.

Ctrl+Z suspend, fg reprend. C’est la pause-play du terminal.

— cheroliv

15. Références