Niveau :      
Résumé : bash fork & exec

Supposons que vous ayez un script que vous voulez faire tourner en arrière plan. Par exemple un script d'init qui s'obstine à vous bloquer le processus de boot alors que vous savez pertinemment qu'il n'est pas indispensable à la suite du processus (pur exemple).

Comment faire ceci simplement ?

Méthode 1 : vous créez un script stub

Écrivez un deuxième script exécutable qui sera appelé à la place du premier et contenant :

#!/bin/sh
/votre/script "$@" &

Inconvénient, vous avez maintenant 2 scripts à gérer et il vous faut changer soit le nom du script original, soit les chemins d'appels. De plus votre 2e script dépend du chemin du premier.

Méthode 2 : vous "démonisez" votre script

Et c'est maintenant que bison futé fait son apparition. L'expérience a fait de bison futé un bison rôdé à toutes les ornières de la route du sysadmin bienheureux.

Voici donc la ligne miracle à déposer en début du script à lancer en arrière plan :

[ -z "$FORK" ] && { FORK=1 $0 "$@" & exit; }

Explications :

  • [ ] -> lance un test
  • -z -> la chaîne à tester est vide (pas encore de fork)
  • && -> équivalent du if, si ce qui est à gauche est vrai on continue l'évaluation
  • { } -> groupe de sous commandes sans sous shell
  • FORK=1 -> variable d'environnement (car juste avant une commande)
  • $0 -> exécute le script dans lequel on est (-> avec FORK à 1 -> false pour le test initial)
  • "$@" -> passe en argument au script exactement ceux qu'on vient de recevoir correctement séparés par des " (pour les espaces)
  • & -> lance la commande précédente en arrière plan, pas besoin de ; après &
  • exit -> arrête définitivement le script en cours (le père)
  • ; -> indispensable à la fin de { }

En résumé, on fait un fork avec les même paramètres + une variable FORK=1 en arière plan et on quitte le script en cours. Dans processus ainsi créé, on continue comme si de rien n'était.