15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer
10.11.2023

Comment activer le chargement automatique de scripts dans Ubuntu : trois méthodes prêtes pour la production

Activer le chargement automatique de scripts dans Ubuntu signifie configurer le système d’exploitation pour exécuter automatiquement un ou plusieurs scripts shell ou services au démarrage du système, sans aucune intervention manuelle. Cela est réalisé grâce à trois mécanismes principaux : le répertoire /etc/init.d/ basé sur le SysVinit hérité, le shim de compatibilité /etc/rc.local, et le framework moderne d’unités de service systemd — ce dernier étant l’approche faisant autorité et recommandée sur toutes les versions d’Ubuntu à partir de la 15.04.

Pour les administrateurs système exécutant des charges de travail dans un environnement VPS Hosting, l’automatisation du démarrage n’est pas une commodité — c’est une exigence de fiabilité. Une entrée de démarrage automatique mal configurée ou absente signifie que les démons critiques, les agents de surveillance, les scripts de sauvegarde ou les configurations réseau personnalisées échouent silencieusement à se lancer après un redémarrage, provoquant des interruptions de service difficiles à diagnostiquer après coup.

Pourquoi l’automatisation des scripts de démarrage est importante sur les serveurs Ubuntu

Chaque serveur Ubuntu en production accumule des scripts opérationnels au fil du temps : routines de préchauffage de base de données, déclencheurs de rotation des journaux, initialiseurs de tunnel VPN, chargeurs de règles de pare-feu et vérifications de l’état des applications. Sans mécanisme de chargement automatique structuré, ces scripts dépendent entièrement d’une exécution manuelle — une seule étape manquée après une mise à jour du noyau ou un redémarrage d’urgence peut se transformer en temps d’arrêt.

L’écosystème d’automatisation du démarrage d’Ubuntu a considérablement évolué :

  • SysVinit (avant Ubuntu 15.04) : Séquentiel, lent, basé sur des scripts. Chaque service bloquait le suivant.
  • Upstart (Ubuntu 6.10–15.04) : Piloté par événements, plus rapide, mais désormais obsolète.
  • systemd (Ubuntu 15.04+) : Activation parallèle des services, graphes de dépendances, activation par socket, contrôle des ressources basé sur les cgroups et journalisation structurée via journald.

Comprendre avec quelle couche vous travaillez — et pourquoi — vous évite de déployer une solution fonctionnelle dans un environnement de test qui échoue silencieusement en production.

Méthode 1 : Utilisation du répertoire /etc/init.d/ (SysVinit / Scripts LSB)

Comment ça fonctionne

Le répertoire /etc/init.d/ est le répertoire traditionnel pour les scripts d’initialisation Linux Standard Base (LSB). Chaque script dans ce répertoire est un script shell qui répond à des commandes standardisées : start, stop, restart, status, et optionnellement reload. L’utilitaire update-rc.d crée des liens symboliques dans les répertoires de niveaux d’exécution /etc/rcN.d/, déterminant quand et dans quel ordre le script s’exécute pendant les séquences de démarrage et d’arrêt.

Sur les systèmes Ubuntu modernes exécutant systemd, ces scripts sont toujours pris en charge via une couche de compatibilité appelée systemd-sysv-generator, qui convertit automatiquement les scripts d’initialisation LSB en unités systemd transitoires. Cela signifie que vos scripts /etc/init.d/ s’exécuteront toujours, mais ils sont encapsulés par systemd plutôt qu’exécutés directement par SysVinit.

Mise en œuvre étape par étape

Étape 1 : Créez votre script

Rédigez votre script et assurez-vous qu’il suit la convention d’en-tête LSB. Un exemple minimal adapté à la production :

#!/bin/bash
### BEGIN INIT INFO
# Provides:          examplescript
# Required-Start:    $remote_fs $syslog $network
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example autoload script
# Description:       Runs a custom initialization task at boot
### END INIT INFO

case "$1" in
  start)
    echo "Starting examplescript..."
    /usr/local/bin/examplescript.sh &
    ;;
  stop)
    echo "Stopping examplescript..."
    pkill -f examplescript.sh
    ;;
  restart)
    $0 stop
    $0 start
    ;;
  status)
    pgrep -f examplescript.sh > /dev/null && echo "Running" || echo "Stopped"
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
    exit 1
    ;;
esac
exit 0

Étape 2 : Placez le script dans /etc/init.d/

sudo cp examplescript /etc/init.d/examplescript

Étape 3 : Rendez-le exécutable

sudo chmod +x /etc/init.d/examplescript

Étape 4 : Enregistrez-le dans le système de niveaux d’exécution

sudo update-rc.d examplescript defaults

L’argument defaults enregistre le script pour démarrer aux niveaux d’exécution 2, 3, 4 et 5, et s’arrêter aux niveaux d’exécution 0, 1 et 6 — le comportement standard pour la plupart des démons serveur.

Étape 5 : Vérifiez l’enregistrement

ls -la /etc/rc2.d/ | grep examplescript

Vous devriez voir un lien symbolique comme S01examplescript pointant vers /etc/init.d/examplescript.

Piège critique

L’erreur la plus courante avec cette méthode est d’omettre le bloc d’en-tête LSB. Sans lui, update-rc.d ne peut pas déterminer l’ordre des dépendances, et systemd-sysv-generator peut attribuer un ordre d’exécution incorrect par rapport à la disponibilité du réseau ou aux montages du système de fichiers. Définissez toujours les dépendances Required-Start explicitement.

Pour supprimer le script du démarrage automatique sans le supprimer :

sudo update-rc.d examplescript disable

Pour le supprimer complètement :

sudo update-rc.d examplescript remove

Méthode 2 : Utilisation de /etc/rc.local (Shim de compatibilité)

Comment ça fonctionne

/etc/rc.local est un mécanisme hérité qui exécute un script shell une seule fois, après que tous les services standard du niveau d’exécution multi-utilisateur ont démarré. C’est la méthode de démarrage automatique la plus simple possible — pas de gestion de service, pas de déclarations de dépendances, pas de logique de redémarrage. Sur Ubuntu 18.04 et versions ultérieures, la prise en charge de rc.local est fournie par l’unité systemd rc-local.service, qui est désactivée par défaut et doit être explicitement activée.

Quand l’utiliser

Utilisez /etc/rc.local uniquement pour :

  • Les commandes d’initialisation ponctuelles qui n’ont pas besoin d’être gérées comme des services
  • Le prototypage rapide ou les tests avant de formaliser une unité systemd
  • Les exportations simples de variables d’environnement ou les ajustements de paramètres du noyau

N’utilisez pas /etc/rc.local pour les démons à longue durée d’exécution. Parce qu’il s’exécute de manière bloquante et séquentielle sans supervision des processus, une commande bloquée dans rc.local retardera ou empêchera la fin de la séquence de démarrage.

Mise en œuvre étape par étape

Étape 1 : Vérifiez si /etc/rc.local existe

ls -la /etc/rc.local

S’il n’existe pas, créez-le :

sudo bash -c 'cat > /etc/rc.local << EOF
#!/bin/bash
exit 0
EOF'
sudo chmod +x /etc/rc.local

Étape 2 : Activez l’unité systemd rc-local (Ubuntu 18.04+)

sudo systemctl enable rc-local
sudo systemctl start rc-local

Étape 3 : Ajoutez votre commande avant exit 0

sudo nano /etc/rc.local

Insérez votre commande au-dessus de la ligne exit 0 :

#!/bin/bash
/usr/local/bin/examplescript.sh >> /var/log/examplescript.log 2>&1 &
exit 0

Le & à la fin est essentiel pour toute commande à longue durée d’exécution — il fait passer le processus en arrière-plan afin que rc.local ne soit pas bloqué.

Étape 4 : Vérifiez l’exécution

sudo systemctl status rc-local

Piège critique

Sur Ubuntu 20.04 et 22.04, rc-local.service a un délai d’expiration codé en dur de 30 secondes. Si votre script prend plus de 30 secondes à se terminer, systemd marquera le service comme échoué et les commandes suivantes dans rc.local ne s’exécuteront pas. Redirigez la sortie et mettez explicitement en arrière-plan les processus à longue durée d’exécution.

Méthode 3 : Utilisation des unités de service systemd (Recommandée)

Pourquoi systemd est la bonne approche pour la production

systemd n’est pas simplement un remplacement de SysVinit — c’est un gestionnaire de système et de session complet qui fournit la résolution des dépendances, le démarrage parallèle, l’activation par socket et D-Bus, la création de services à la demande, la supervision des processus avec redémarrage automatique, l’isolation des ressources basée sur les cgroups et l’agrégation structurée des journaux via journald. Pour toute charge de travail s’exécutant sur un Serveur Dédié ou un VPS en production, les unités systemd sont le seul mécanisme approprié pour gérer les scripts chargés automatiquement.

Anatomie d’un fichier d’unité systemd

Un fichier d’unité .service est divisé en trois sections obligatoires :

  • [Unit] : Métadonnées, description lisible par l’homme et déclarations de dépendances (After=, Requires=, Wants=).
  • [Service] : Paramètres d’exécution — le binaire ou script à exécuter, le type de service, la politique de redémarrage, les variables d’environnement et les options de sandboxing de sécurité.
  • [Install] : Définit quelle cible systemd active cette unité (WantedBy=multi-user.target est le standard pour les démons serveur).

Mise en œuvre étape par étape

Étape 1 : Préparez votre script

Assurez-vous que votre script est exécutable et situé dans un chemin stable :

sudo cp examplescript.sh /usr/local/bin/examplescript.sh
sudo chmod +x /usr/local/bin/examplescript.sh

Étape 2 : Créez le fichier d’unité

sudo nano /etc/systemd/system/examplescript.service

Un fichier d’unité de qualité production avec durcissement de sécurité :

[Unit]
Description=Example Autoload Script
Documentation=https://your-internal-wiki/examplescript
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/examplescript.sh
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=examplescript
User=nobody
Group=nogroup
NoNewPrivileges=true
ProtectSystem=strict
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Étape 3 : Rechargez le démon systemd

Après avoir créé ou modifié un fichier d’unité, vous devez recharger l’index de configuration du démon :

sudo systemctl daemon-reload

Étape 4 : Activez le service pour le démarrage automatique

sudo systemctl enable examplescript.service

Cela crée un lien symbolique dans /etc/systemd/system/multi-user.target.wants/ pointant vers votre fichier d’unité.

Étape 5 : Démarrez le service immédiatement

sudo systemctl start examplescript.service

Étape 6 : Vérifiez l’état et les journaux

sudo systemctl status examplescript.service
sudo journalctl -u examplescript.service -f

Comprendre les types de services systemd

La directive Type= dans la section [Service] est l’un des paramètres les plus mal compris. Choisir le mauvais type amène systemd à mal rapporter la disponibilité du service, entraînant des échecs de dépendances.

TypeComportementCas d’utilisation
simpleLe processus démarré par ExecStart est le processus principal. Systemd le considère prêt immédiatement.Scripts et démons simples qui ne se dupliquent pas
forkingLe processus se duplique et le parent se termine. Systemd suit l’enfant via le fichier PID.Démons Unix traditionnels (ex. Apache avec PidFile)
oneshotLe processus s’exécute jusqu’à la fin et se termine. Systemd attend avant de démarrer les unités dépendantes.Tâches d’initialisation ponctuelles, scripts de configuration
notifyLe processus signale sa disponibilité via sd_notify().Démons avec intégration systemd native
idleL’exécution est retardée jusqu’à ce que tous les travaux actifs soient distribués.Tâches en arrière-plan de faible priorité

Pour un script qui s’exécute une seule fois au démarrage et se termine, utilisez Type=oneshot avec RemainAfterExit=yes pour maintenir l’unité dans un état « actif » après la fin du script.

Avancé : Ordonnancement des dépendances avec After= et Wants=

Un échec courant en production se produit lorsqu’un script nécessitant une connectivité réseau démarre avant que la pile réseau soit entièrement initialisée. La chaîne de dépendances correcte pour les scripts dépendants du réseau est :

After=network-online.target
Wants=network-online.target

Cela est distinct de After=network.target, qui garantit uniquement que les interfaces réseau ont été configurées — pas qu’elles sont réellement en ligne et accessibles. La dépendance network-online.target nécessite que systemd-networkd-wait-online.service ou équivalent confirme la connectivité.

Comparaison : Les trois méthodes en un coup d’œil

Fonctionnalité/etc/init.d//etc/rc.localUnité systemd
Recommandé pour la productionNonNonOui
Prise en charge du démarrage parallèleNonNonOui
Supervision des processus / redémarrage automatiqueNonNonOui
Gestion des dépendancesLimitée (en-têtes LSB)AucuneComplète
Journalisation structuréeNonNonOui (journald)
Sandboxing de sécuritéNonNonOui
ComplexitéFaibleTrès faibleMoyenne
Pris en charge sur Ubuntu 22.04+Via couche de compatibilitéVia rc-local.serviceNativement
Adapté aux démons à longue durée d’exécutionPartiellementNonOui
Adapté aux tâches d’initialisation ponctuellesOuiOuiOui (oneshot)

Erreurs courantes et comment les éviter

Exécuter des scripts en tant que root inutilement. Les directives User= et Group= dans les fichiers d’unité systemd vous permettent de réduire les privilèges. Un script qui n’a besoin que d’écrire dans /var/log/myapp/ n’a pas besoin de root — créez un utilisateur système dédié et attribuez la propriété du répertoire en conséquence.

Ne pas rediriger la sortie dans rc.local. Sans redirection de sortie, toute sortie echo ou sortie d’erreur des commandes rc.local va vers la console système et est perdue. Ajoutez toujours >> /var/log/yourscript.log 2>&1.

Utiliser des chemins absolus de manière incohérente. Les services systemd s’exécutent dans un environnement minimal sans le PATH de l’utilisateur. Utilisez toujours des chemins absolus pour chaque binaire référencé dans ExecStart, y compris les interpréteurs comme /usr/bin/python3 ou /bin/bash.

Oublier daemon-reload après avoir modifié les fichiers d’unité. systemd met en cache le contenu des fichiers d’unité. Si vous modifiez un fichier .service et n’exécutez pas sudo systemctl daemon-reload, systemd continuera à utiliser l’ancienne configuration.

Placer les fichiers d’unité dans /lib/systemd/system/ pour les scripts personnalisés. Le répertoire /lib/systemd/system/ est géré par le gestionnaire de paquets. Les fichiers d’unité personnalisés appartiennent à /etc/systemd/system/, qui a la priorité et survit aux mises à jour des paquets.

Matrice de décision pratique : Quelle méthode utiliser

Utilisez ce cadre pour sélectionner la méthode appropriée à votre scénario spécifique :

  • Démon à longue durée d’exécution qui doit redémarrer en cas d’échec — Unité systemd avec Restart=on-failure
  • Script de configuration ponctuel qui doit se terminer avant le démarrage des autres services — Unité systemd avec Type=oneshot et dépendances Before=
  • Script nécessitant que le réseau soit entièrement en ligne — Unité systemd avec After=network-online.target
  • Commande rapide pour les tests ou le prototypage/etc/rc.local (temporairement)
  • Application héritée fournie avec un script d’initialisation LSB/etc/init.d/ avec update-rc.d
  • Tout ce qui s’exécute en production — systemd, toujours

Pour les administrateurs gérant plusieurs serveurs Ubuntu, envisagez de combiner la gestion des unités systemd avec des outils de gestion de configuration tels qu’Ansible, qui peut déployer et activer des fichiers .service de manière idempotente sur l’ensemble de votre parc. Si vous avez besoin d’un environnement géré avec un accès root complet pour implémenter ces configurations, le VPS Hosting avec un Panneau de contrôle VPS offre la flexibilité nécessaire pour gérer les services systemd directement sans restrictions.

Pour les équipes exécutant des charges de travail gourmandes en ressources nécessitant des scripts de démarrage pour initialiser les pilotes GPU, les environnements CUDA ou les serveurs d’inférence ML, les environnements GPU Hosting bénéficient particulièrement des chaînes de dépendances After= de systemd, garantissant que les pilotes sont entièrement chargés avant que les services applicatifs tentent de se lier aux ressources matérielles.

Si vos scripts chargés automatiquement interagissent avec des configurations de serveur web ou des routines d’initialisation de base de données liées à un environnement de panneau de contrôle, les installations VPS avec cPanel nécessitent une attention particulière — cPanel gère sa propre couche de supervision des services, et les unités systemd personnalisées doivent être définies pour éviter les conflits avec les hooks de gestion des services de cPanel.

Liste de contrôle des points techniques essentiels

Avant de déployer un script de démarrage sur un serveur Ubuntu, vérifiez les points suivants :

  • Emplacement du fichier d’unité : Les scripts personnalisés vont dans /etc/systemd/system/, pas dans /lib/systemd/system/
  • Bit exécutable : Confirmez avec ls -la /path/to/script.sh — le bit x doit être défini
  • Chemins absolus : Chaque binaire dans ExecStart utilise un chemin complet ; aucune dépendance à $PATH
  • Déclarations de dépendances : After=network-online.target pour tout script dépendant du réseau
  • Type de service : Type=simple pour les démons persistants, Type=oneshot pour les scripts d’exécution et de sortie
  • Minimisation des privilèges : User=, Group=, NoNewPrivileges=true, ProtectSystem=strict
  • Journalisation configurée : StandardOutput=journal et StandardError=journal pour l’intégration journald
  • daemon-reload exécuté : Exécutez toujours sudo systemctl daemon-reload après avoir créé ou modifié des fichiers d’unité
  • Enable vs. start : enable crée le lien symbolique de démarrage automatique ; start l’exécute immédiatement — les deux sont nécessaires
  • Testé avec journalctl : Confirmez l’exécution réussie avec sudo journalctl -u yourservice.service --since "5 minutes ago"

FAQ

Quelle est la différence entre systemctl enable et systemctl start ?

systemctl enable crée un lien symbolique qui fait démarrer le service automatiquement au prochain démarrage. systemctl start démarre le service immédiatement dans la session en cours. Vous avez généralement besoin des deux commandes lors de la configuration d’un nouveau service pour la première fois.

Pourquoi mon service systemd échoue-t-il avec « executable not found » même si le script existe ?

Cela signifie presque toujours que le chemin ExecStart est incorrect ou que le script n’a pas le bit exécutable. Vérifiez avec which yourscript et ls -la /path/to/script. Confirmez également que la première ligne de votre script est un shebang valide (#!/bin/bash ou #!/usr/bin/env python3), car systemd n’invoque pas un shell par défaut pour ExecStart.

Puis-je exécuter un script au démarrage une seule fois, pas à chaque démarrage ?

Utilisez Type=oneshot avec une directive ConditionPathExists=!/var/run/myscript.done dans la section [Unit]. Le script crée le fichier sentinelle lors de la première exécution ; les démarrages suivants ignorent l’exécution car la condition échoue.

/etc/rc.local est-il toujours pris en charge sur Ubuntu 22.04 ?

Oui, mais il est désactivé par défaut. Vous devez activer manuellement l’unité rc-local.service avec sudo systemctl enable rc-local et vous assurer que le fichier existe et est exécutable. Il est pris en charge comme mesure de compatibilité, et non comme pratique recommandée.

Comment puis-je vérifier pourquoi un script de démarrage n’a pas réussi à s’exécuter ?

Exécutez sudo journalctl -u yourservice.service -b pour afficher toutes les entrées de journal de cette unité depuis le dernier démarrage. Pour les échecs de rc.local, vérifiez sudo systemctl status rc-local.service et consultez /var/log/syslog pour les entrées horodatées pendant la séquence de démarrage.

15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer