Linux Nohup pour détacheer un process shell

Lorsque vous quittez un shell, tous les process lancées sont arrêtés. Ce qui est ok si vous arrêtez de travaillez, mais imaginez que vous avez un process qui prend beaucoup de temps, par exemple la conversion d’une vidéo, vous avez intérêt à garder le shell ouvert.

Cependant il existe une commande Linux qui permet de lancer un process dans un shell et de le fermer sans interrompre son exécution : c’est nohup. Il n’est pas forcément installé par défaut dans ce cas voici ce qu’il faut faire pour l’installer sous Ubuntu/Debian :

sudo apt update
sudo apt install coreutils

Comment utiliser nohup

# par exemple un script de conversion en python
python convertisseur.py

#pour lancer avec la possibilité de fermer le shell sans arrêter le programme
nohup python convertisseur.py

# pour un script shell
nohup ./monscript.sh

# pour une commande
nohup curl -O https://monsite.com

Pour ça s’appelle nohup?

En Linux, il existe un appel système SIGHUP qui va arrêter un process. Nohup va simplement empêcher cet appel d’affecter un process lancé avec lui, d’où le nom No HUP.

Mise en application de nohup

Nous allons lancer un process qui va prendre du temps, mais tout simple, et que nous allons passer avec nohup dans un second temps

ping google.fr

PING google.com (142.250.201.46) 56(84) bytes of data.
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=1 ttl=115 time=24.5 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=2 ttl=115 time=13.8 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=3 ttl=115 time=8.44 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=4 ttl=115 time=12.3 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=5 ttl=115 time=8.01 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=6 ttl=115 time=11.8 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=7 ttl=115 time=8.41 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=8 ttl=115 time=9.02 ms

Le ping ne va pas s’arrêter, il prend la main sur le shell. Lançon maintenant avec nohup

nohup ping google.com

nohup: ignoring input and appending output to 'nohup.out'

A ce stade nohup ne vous rend pas la main, mais ouvrez une seconde fenêtre pour afficher le contenu du fichier nohup.out comme indiqué dans le message, vous verrez le même contenu que précédemment. Si vous faites CTRL + C pour arrêter, le process s’arrête. Jusqu’ici nohup n’a pas montré sa valeur ajoutée.

Vous pouvez aussi rediriger vers un fichier spécifique au lieu du fichier par défaut nohup.out.

nohup ping google.com > journal.txt

Un mot à propos de stdout et stderr et stdin

stdout est ce qu’on appelle la sortie standard, en réalité la sortie standard c’est ce que vous voyez à l’écran. Mais il y a stderr, qui est la sortie d’erreur, donc où s’affiche les erreurs? à l’écrant également ! mais on fait le distingo entre la sortie standard et la sortie d’erreur.

On dira que stderr est un flux de sortie, ce qui est très générique comme appellation. ET ne pas oublier qu’il y a stdin ! qui est le flux d’entrée. Il faut savoir que chaque flux possède un numéro de descripteur, stdin a 0, stdout a 1 et stderr a 2. Connaitres ces numéro va nous permettre de mieux comprendre la commande suivante. Donc stdout et stderr affichent tous les deux à l’écran !

Mais on peut faire autrement, ainsi on peut rediriger les erreurs vers un fichier error.log par exemple.

ls /etc /non_existent_dir

ls: cannot access '/non_existent_dir': No such file or directory   << erreur
/etc:   << sortie standard pas d'erreur
adduser.conf                   deluser.conf  ldap            mtab                 rc2.d         sudoers.d
alternatives                   depmod.d      ld.so.cache     nanorc               rc3.d         sudo_logsrvd.conf
apache2                        dhcp          ld.so.conf      netconfig            rc4.d         sysctl.conf
apparmor                       dpkg          ld.so.conf.d    netplan              rc5.d         sysctl.d
apparmor.d                     e2scrub.conf  legal           networkd-dispatcher  rc6.d         systemd

Ici on essait de faire ls sur un répertoire inexistant, donc ça va provoquer une erreur

ls /etc /non_existent_dir  2> errors.txt

dans l’exemple ci-dessus, on va ridiriger les erreurs vers un fichier errors.txt, et ce qui ne déclenche pas d’erreur sort à l’écran.

ls /etc /non_existent_dir > output.txt 2> errors.txt

L’exemple ci-dessus va rediriger les données vers output.txt, et s’il y a des erreurs, va rediriger vers errors.txt

Une syntaxe plus cryptique:

ls /etc /non_existent_dir > fusion.txt 2>&1

L’exemple ci-dessus va rediriger le flux d’erreur (numéro 2) vers le flux 1, donc les erreurs iront au fichier fusion.txt

Encore un mot sur comment lire stdin

tee input.txt   // ce qui est tapé est affiché à l'écran et enregistré dans input.txt
faire CTRL+D pour arrêter

on peut utiliser aussi cat

$ cat > input.txt  // ce qui est tapé n'est pas affiché à l'écran, donc pas de doublon à l'écran CTRL+D pour arrêter

Utiliser la commande script pour tout enregistrer dans un fichier

script input.txt  // taper exit ou CTRL+D pour sortir

Démarrer un process en background avec nohup (arrière plan)

$ nohup ping google.com &
[1] 8519   // numéro aléatoire
nohup: ignoring input and appending output to 'nohup.out'

Pour afficher le processus faire :
$ pgrep -a ping

8519 ping google.com

pour tuer le process :
kill -9 8519

Cette fois-ci nohup vous rend la main. ON va refaire avec un fichier de sortie

nohup ping google.com > output.txt  &
Retour en haut