BASH : lancer une tâche en arrière-plan et fermer le terminal sans interrompre la tâche

J’ai récemment mis à jour mon article sur Rsync pour rapatrier quelques fichiers d’un serveur vers mon NAS Synology. Or, une question revient vite dès qu’une commande doit tourner pendant plusieurs heures : comment lancer une tâche depuis un terminal, fermer ce terminal, puis laisser la commande continuer tranquillement ?

Par défaut, ce n’est pas toujours gagné. Quand on ferme un terminal, le shell peut envoyer un signal SIGHUP aux processus qu’il a lancés. Résultat : la commande peut s’arrêter, même si elle était encore en train de travailler.

Heureusement, Bash propose plusieurs méthodes pour lancer une commande en arrière-plan, la détacher du terminal, ou même retrouver une session plus tard. Voici les solutions que je garde sous le coude.

Lancer une commande en arrière-plan avec &

La méthode la plus simple consiste à ajouter une esperluette & à la fin de la commande. Bash lance alors le processus en arrière-plan et rend immédiatement la main au terminal.

sleep 100 &

Le shell affiche alors un numéro de job et un identifiant de processus, aussi appelé PID :

[1] 12345Code language: JSON / JSON with Comments (json)

C’est pratique, mais ce n’est pas suffisant si vous voulez fermer le terminal sans risque. La commande reste encore rattachée à la session du shell.

On peut vérifier les tâches lancées depuis le shell courant avec :

jobs

Et on peut vérifier que le processus tourne toujours avec :

ps aux | grep sleep

Détacher une tâche avec disown

La commande disown permet de retirer un job de la table des tâches du shell. En clair, Bash ne le surveille plus. Ainsi, lorsque le terminal se ferme, le shell ne tente plus de gérer cette commande.

On peut lancer une commande en arrière-plan, puis la détacher immédiatement :

sleep 600 &
disown

Ou bien, plus compact :

sleep 600 & disown

À partir de là, vous pouvez fermer le terminal. Le processus devrait continuer à tourner.

Pour une vraie commande longue, comme un transfert Rsync, cela donne par exemple :

rsync -avh --progress /home/www/ user@nas:/volume1/backups/www/ & disownCode language: JavaScript (javascript)

Petit bémol tout de même : si la commande écrit dans le terminal, sa sortie peut devenir gênante, voire provoquer des comportements inattendus après la fermeture de la session. Il vaut donc mieux rediriger la sortie standard et les erreurs vers un fichier de log.

rsync -avh /home/www/ user@nas:/volume1/backups/www/ > ~/rsync-backup.log 2>&1 & disownCode language: JavaScript (javascript)

On peut ensuite suivre l’avancement avec :

tail -f ~/rsync-backup.log

Utiliser nohup

nohup signifie “no hangup”. La commande sert justement à ignorer le signal SIGHUP, souvent envoyé lorsqu’un terminal se ferme.

Exemple simple :

nohup sleep 600 &

Par défaut, nohup écrit la sortie de la commande dans un fichier nommé nohup.out, dans le répertoire courant ou dans votre dossier personnel.

Pour une commande longue, je préfère être explicite et définir moi-même le fichier de log :

nohup rsync -avh /home/www/ user@nas:/volume1/backups/www/ > ~/rsync-backup.log 2>&1 &Code language: JavaScript (javascript)

C’est simple, robuste, et suffisant pour une commande ponctuelle que l’on n’a pas besoin de reprendre en main ensuite.

Créer un sous-shell

On peut aussi lancer une commande dans un sous-shell avec des parenthèses. Le signe & lance ce sous-shell en arrière-plan, puis exit permet de quitter le terminal proprement.

(sleep 100) & exitCode language: PHP (php)

On peut ensuite ouvrir un autre terminal et vérifier que la tâche tourne toujours :

ps aux | grep sleep

Cette méthode fonctionne dans certains cas simples, mais elle reste moins explicite que nohup, disown ou screen. Pour une tâche vraiment importante, je préfère une solution plus lisible et plus facile à reprendre.

Utiliser screen pour garder une session récupérable

La commande screen change un peu d’approche. Au lieu de simplement détacher une commande, elle crée une session terminal indépendante. Vous pouvez lancer une commande dedans, vous détacher de la session, fermer votre terminal, puis revenir plus tard exactement là où vous en étiez.

C’est parfait pour les commandes longues que vous voulez surveiller, comme un rsync, une restauration de base de données, une compilation, une migration WordPress, ou un script qui affiche une progression utile.

Pour créer une session nommée :

screen -S backup-rsync

Vous vous retrouvez alors dans un nouveau terminal virtuel. Lancez votre commande normalement :

rsync -avh --progress /home/www/ user@nas:/volume1/backups/www/Code language: JavaScript (javascript)

Pour vous détacher de la session sans arrêter la commande, utilisez le raccourci suivant :

Ctrl + A, puis D

Le terminal affiche alors quelque chose comme :

[detached from 12345.backup-rsync]Code language: JSON / JSON with Comments (json)

Vous pouvez maintenant fermer le terminal. La commande continue dans la session screen.

Pour lister les sessions existantes :

screen -ls

Pour reprendre la session plus tard :

screen -r backup-rsync

Si vous n’avez qu’une seule session ouverte, cette commande suffit souvent :

screen -r

Enfin, pour quitter définitivement une session screen, il suffit de terminer la commande en cours, puis de taper :

exitCode language: PHP (php)

screen est donc la meilleure option lorsque vous voulez pouvoir revenir dans votre terminal plus tard. Contrairement à nohup ou disown, vous ne vous contentez pas de lancer une tâche dans le vide : vous gardez une vraie session interactive.

Quelle méthode choisir ?

Pour une commande rapide que vous voulez simplement envoyer en arrière-plan, & suffit.

Pour une commande ponctuelle qui doit continuer après la fermeture du terminal, nohup avec une redirection vers un fichier de log reste une valeur sûre.

Pour une commande déjà lancée en arrière-plan, disown permet de la détacher du shell courant.

Enfin, pour une tâche longue que vous voulez pouvoir suivre et reprendre plus tard, screen est beaucoup plus confortable.

Dans mon cas, pour un gros transfert rsync, j’utilise généralement screen. C’est plus propre, plus lisible, et surtout moins stressant quand la copie dure plusieurs heures. Fermer un terminal sans faire tomber une sauvegarde, c’est tout de même meilleur pour le rythme cardiaque.

Mémo rapide

# Lancer en arrière-plan.
commande &

# Lancer en arrière-plan puis détacher du shell.
commande & disown

# Ignorer la fermeture du terminal et écrire dans un log.
nohup commande > ~/commande.log 2>&1 &

# Créer une session screen nommée.
screen -S nom-session

# Se détacher d'une session screen.
Ctrl + A, puis D

# Lister les sessions screen.
screen -ls

# Reprendre une session screen.
screen -r nom-sessionCode language: PHP (php)

À garder sous le coude.

Gravatar for Matt Biscay

Je suis Matt Biscay, développeur WordPress & WooCommerce certifié chez Codeable, administrateur système et enseignant.

J’aide les entreprises à créer, optimiser et fiabiliser leurs sites WordPress avec une approche technique propre : performance, sécurité, maintenance, développement sur mesure et résolution de problèmes complexes.

Sur Skyminds, je partage des tutoriels WordPress, WooCommerce, Linux et administration système, avec des solutions testées sur des cas réels et pensées pour durer.

Découvrez mes services WordPress et WooCommerce.

2 pensées sur “BASH : lancer une tâche en arrière-plan et fermer le terminal sans interrompre la tâche”

  1. Y’a aussi avec screen, qui permet de créer des terminaux “virtuels”:
    screen -S rsync
    *on lace rsync etc*
    Pour revenir au terminal principal : ctrl+a, d
    Et pour revenir sur rsync : screen -r rsync

    Reply

Opinions