Quel est le substitut correct de rc.local dans systemd au lieu de recréer rc.local

25

Je ne trouve pas la bonne façon d'exécuter certains scripts locaux (ou des commandes très locales) sur systemd, je sais déjà que je ne dois pas créer de service (dans systemd une unité) pour ce genre de scripts (ou je dois?) ....

La solution de contournement que j'ai trouvée est de créer rc.local et de lui donner des autorisations d'exécution.

printf '#!/bin/bash \n\nexit 0' >/etc/rc.local 
chmod +x /etc/rc.local

Par exemple, si j'obtiens un serveur hérité avec un simple rc.local configuré par vous, je saurai ce que vous avez fait et combien ça va faire mal de mettre à niveau ou d'installer quelque chose de nouveau sur la distribution, car rc.local a été respecté par les externes packages, mais d'autre part si j'installe un serveur et crée une unité systemd ou deux ou trois (ou même des services sysvinit), juste pour faire une tâche simple, cela peut parfois vous rendre la vie plus difficile, et bien plus que cela mes unités les noms peuvent un jour entrer en conflit avec les noms des nouveaux services créés par le développement de la distribution, et peuvent être installés sur une mise à niveau, causant des problèmes pour mes scripts!

Je vois une autre question demandant où est rc.local et la réponse a été de le créer et de donner des autorisations d'exécution, je pense que ma question n'est vraiment pas un doublon , parce que je ne veux pas savoir où elle est - croyez-moi, je veux juste d' accepter qu'il est obsolète , mais je ne trouve pas la bonne façon de faire ce genre de choses, devrais-je vraiment créer une unité juste pour quelques simples comme ça?

Luciano Andress Martini
la source
4
systemd "le seul coup gagnant est de ne pas jouer"; alternativement, selon ce que vous voulez, vous pouvez créer une unité systemd. J'utiliserais probablement rc.local pour l'instant, et je m'en soucierais quand il disparaîtrait.
Rui F Ribeiro
Vous pensez donc que la manière officielle est de créer une unité comme un service? Veuillez poster comme réponse comment faire cela.
Luciano Andress Martini
1
Quand j'ai essayé Ubuntu, j'ai créé une unité pour avoir une mise en cache persistante d'agent ssh sur mon bureau alors que je n'ai pas redémarré et une autre pour autre chose dont je ne me souviens pas; vous pouvez également en créer un pointant vers /etc/rc.local mais il semble que le système le fasse pour vous pour l'instant .... Je voudrais rc.local pour le moment, et s'il est interrompu, créer un pointant vers un faux /etc/rc.local alors.
Rui F Ribeiro
Cela risque de casser les documentations comme si certains livres disaient que vous devez mettre quelque chose dans /etc/rc.local, et vous essayez de mettre à jour cette documentation, en disant par exemple que rc.local doit être marqué comme exécutable, quand il devient totalement obsolète la documentation est cassée, mais si vous dites que vous devez créer une unité pour pointer vers /etc/rc.local, cela casse la documentation car systemd est en conflit avec votre unité. Je crois que si vous avez raison, ils n'ont probablement pas décidé si elle est dépréciée ou non, car ils n'ont toujours pas de substitut ... lorsqu'ils décident que toute la documentation sera à nouveau cassée.
Luciano Andress Martini
Quel type de script devez-vous exécuter? Systemd a beaucoup de types d'unités. Le «service» n'est que l' un des nombreux types d'unités . Par exemple, monter des unités, des unités de montage automatique, des unités de temporisation, des unités cibles. L'un d'eux pourrait-il résoudre votre problème?
andcoz

Réponses:

17

Comme indiqué ailleurs, il devient modérément impur à utiliser rc-local.servicesous systemd.

  1. Il est théoriquement possible que votre distribution ne le permette pas. (Je pense que ce n'est pas courant, par exemple parce que la désactivation de la même option de construction supprime également poweroff/reboot commandes que beaucoup de gens utilisent).
  2. La sémantique n'est pas entièrement claire. Systemd définit rc-local.serviceune façon, mais Debian fournit un fichier de dépôt qui modifie au moins un paramètre important.

rc-local.servicepeut souvent bien fonctionner. Si vous vous inquiétez de ce qui précède, il vous suffit d'en faire votre propre copie! Voici la magie:

# /etc/systemd/system/my-startup.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/libexec/my-startup-script

[Install]
WantedBy=multi-user.target

Je ne pense pas que vous ayez besoin de comprendre chaque détail [*], mais il y a deux choses que vous devez savoir ici.

  1. Vous devez l'activer avec systemctl enable my-startup.service.

  2. Si votre script a une dépendance sur tout autre service, y compris network-online.target, vous devez le déclarer. Par exemple, ajoutez une [Unit]section, avec les lignes Wants=network-online.targetetAfter=network-online.target .

    Vous n'avez pas à vous soucier des dépendances des services de "démarrage précoce" - en particulier, les services qui sont déjà commandés auparavant basic.target. Les services comme my-startup.servicesont automatiquement commandés après basic.target, sauf s'ils sont définis DefaultDependencies=no.

    Si vous ne savez pas si l'une de vos dépendances est un service de «démarrage rapide», une approche consiste à répertorier les services qui sont commandés avant basic.target, en exécutant systemctl list-dependencies --after basic.target. (Notez que ce n'est --afterpas le cas --before).

Il y a quelques considérations qui, je pense, s'appliquent également à la version pré-système rc.local:

  1. Vous devez vous assurer que vos commandes ne sont pas en conflit avec un autre programme qui essaie de contrôler la même chose.
  2. Il est préférable de ne pas démarrer de programmes de longue durée appelés démons rc.local.

[*] J'ai utilisé Type=oneshot+ RemainAfterExit=yescar cela a plus de sens pour la plupart des scripts one-shot. Il formalise que vous exécuterez une série de commandes, qui my-startupseront affichées comme "actives" une fois qu'elles seront terminées, et que vous ne démarrerez pas un démon.

sourcejedi
la source
Eh bien, il existe une sorte de lieu "local" pour créer des services ou des extraits de code, ou quoi que ce soit - ou puis-je avoir confiance que cela est local et ne devrait pas être modifié? si je développe mes propres démons? Parce que je ne veux pas modifier l'originalité du système, donc quand j'installe un apt-get, je ne veux pas voir mon système en feu à cause d'un script remplacé, ou quelque chose comme ça par exemple. Je veux juste avoir confiance que le démon ne sera démarré qu'une seule fois, sans faire de choses folles supplémentaires que je crains ... comme essayer de le redémarrer à l'infini s'il est cassé, etc ...
Luciano Andress Martini
1
@LucianoAndressMartini si vous demandez quelle est la bonne façon de démarrer un démon, vous devez vraiment définir un service individuel pour lui. Cela peut être une .serviceunité système native , ou si vous voulez vraiment écrire un script d'initialisation LSB, vous pouvez le faire à la place. Je ne voulais pas recommander de mettre plusieurs démons dans rc-local.serviceou équivalent, je pense que cela fonctionne probablement, mais cela semble beaucoup plus agréable si vous pouvez redémarrer le démon individuel avec systemctl restart my-daemoncomme n'importe quoi d'autre. Il est prévu que vous mettiez vos services locaux /etc/systemd/system.
sourcejedi
1
@LucianoAndressMartini, vous devez éviter d'utiliser le même nom que tout autre service - tout comme dans sysvinit. Dans des situations similaires, j'ai parfois commencé mon nom avec local-...
sourcejedi
1
Merci!!! Enregistré après une demi-journée. Ces détails étaient essentiels pour moi: Type = oneshot, RemainAfterExit = yes, Wants = network-online.target, After = network-online.target. Il suffit de déployer une version d'apache et de définir l'IP statique sur 192.168.1.80, afin que le routeur puisse y diriger le trafic. Devrait être trivial. C'est ennuyeux dans Debian9. Pratiquement aucun conseil en ligne, sauf "apt-get apache", "systemctl start apache" ou des instructions avec init.d, dont aucun ne s'applique à Apache construit en source sous Debian9.
MichaelsonBritt
1
@MichaelsonBritt Il est préférable de ne pas démarrer de programmes de longue duréeType=oneshot appelés démons à partir de rc.local. J'ai utilisé ... cela formalise que ... vous ne démarrerez pas un démon. Si vous souhaitez des informations sur le démarrage d'un démon, veuillez poser une nouvelle question.
sourcejedi
15

Oubliez rc.local.

Comme je l'ai dit à propos de CentOS 7 et de Debian 8 et d'Ubuntu 15 :

Vous utilisez un système d'exploitation systemd + Linux. /etc/rc.localest un mécanisme de double compatibilité descendante dans systemd, car il s'agit d'un mécanisme de compatibilité descendante pour un mécanisme qui était lui-même un mécanisme de compatibilité dans le système van Smoorenburg 5rc clone .

L'utilisation /etc/rc.localpeut mal tourner. Les gens ont été surpris par le fait que systemd ne fonctionne rc.localpas de la même manière, au même endroit dans le bootstrap, comme ils sont habitués. (Ou attendez-vous à tort: ​​en fait, il ne fonctionnait pas en dernier dans l'ancien système, comme le souligne encore le manuel d'OpenBSD.) D'autres ont été surpris par le fait que ce qu'ils ont mis en place en rc.locals'attendant aux anciennes façons de faire, est puis complètement défaits par les goûts de nouvelles udevrègles, NetworkManager, systemd-logind, systemd-resolvedou divers « Kit » s.

Comme illustré par « Pourquoi« init 0 »entraîne-t-il des« Arguments excédentaires »lors de l'installation d'Arch? », Certains systèmes d'exploitation fournissent déjà systemd sans les fonctionnalités de compatibilité descendante telles que le systemd-rc-local-generatorgénérateur . Alors que Debian conserve toujours les fonctionnalités de compatibilité descendante , Arch Linux construit systemd avec elles désactivées . Ainsi, sur Arch et les systèmes d'exploitation comme celui-ci, ils /etc/rc.local devraient être entièrement ignorés .

Oubliez rc.local. Ce n'est pas la voie à suivre. Vous avez un système d'exploitation systemd + Linux. Faites donc une unité de service systemd appropriée et ne partez pas d'un point qui est à deux niveaux de compatibilité descendante. (Sur Ubuntu et Fedora, il a été supprimé à trois reprises, le rcclone van Smoorenburg System 5 qui a suivi rc.localayant ensuite été lui-même remplacé deux fois , il y a plus de dix ans, d'abord par un parvenu puis par systemd.)

Souvenez-vous également de la première règle de migration vers systemd .

Ce n'est même pas une nouvelle idée spécifique à systemd. Sur les rcsystèmes van Smoorenburg et Upstart, la chose à faire était de créer un rcscript van Smoorenburg ou un fichier de travail Upstart approprié plutôt que de l'utiliser rc.local. Même le manuel de FreeBSD note qu'aujourd'hui, on crée un rcscript Mewburn approprié au lieu de l'utiliser /etc/rc.local. Mewburn a rcété introduit par NetBSD 1.5 en 2000.

/etc/rc.localdate de l'époque de la septième édition Unix et avant. Il a été remplacé /etc/inittabet basé rcsur un niveau d'exécution dans AT&T Unix System 3 (avec un peu différent /etc/inittabdans AT&T Unix System 5) en 1983 . Même cela appartient désormais à l'histoire.

Créez des définitions de service natives appropriées pour votre système de gestion des services, qu'il s'agisse d'un ensemble de services pour l'ensemble d'outils Nosh service-manageret system-control, d'un /etc/rc.d/script pour Mewburn rc, d'un fichier d'unité de service pour systemd, d'un fichier de travail pour Upstart, d'un répertoire de service pour runit / s6 / daemontools -encore, ou même un /etc/init.d/script pour van Smoorenburg rc.

Dans systemd, ces fichiers d'unité de service ajoutés par l'administrateur entrent /etc/systemd/system/généralement (ou /usr/local/lib/systemd/system/rarement). Avec le nosh service manager, /var/local/sv/est un lieu conventionnel pour les bundles de services locaux. Mewburn rcsur les utilisations de FreeBSD /usr/local/etc/rc.d/. Les fichiers d'unité de service et les packs de services, si vous les créez, vont cependant à des endroits différents.

Lectures complémentaires

JdeBP
la source
2
@LucianoAndressMartini Une meilleure question serait de savoir comment gérer un extrait spécifique de rc.local dans un service systemd. Donc, si vous avez un extrait spécifique à l'esprit (vous mentionnez des instructions de la documentation de certains logiciels), peut-être publier une question à ce sujet à la place? Il existe certaines règles générales qui peuvent être utilisées pour la conversion, mais vous en tirez le meilleur parti en exploitant les fonctionnalités du logiciel que vous exécutez (telles que l'exécution au premier plan, sans essayer de démoniser, etc.), alors posez des questions sur un cas spécifique. pourrait être utile.
filbranden
4
Vous devez vous demander s'il a survécu à la dépréciation depuis 1983, peut-être qu'il a quelque chose pour ça?
dan carter
4
Cette réponse est prêche et ne parvient pas à répondre à la simple question «quelle chose triviale dois-je faire à la place». Il peut contenir des informations et fournir des tonnes de références, mais va à l'encontre du but de stackexchange.
gps
J'apporte cela (la fin de rc.local), ainsi que la résolution de problèmes par DNS, comme raisons pour lesquelles Linux n'évolue pas, mais en réalité, de plus en plus en code spaghetti, systemd est devenu une boîte noire pour beaucoup. Si un utilisateur ou un administrateur veut mettre quelque chose dans rc.local et ne le peut plus, il n'est pas utile de le forcer à faire d'abord des cours systemd ou tout ce que vous prêchez afin d'obtenir le même résultat final en jours, au lieu de minutes. Bien sûr, les idiots peuvent faire des choses stupides avec tout ce qui fonctionne bien et est facile à travailler, ce n'est jamais un argument valable pour y mettre fin.
Julius
2

Résumé de https://www.linuxbabe.com/linux-server/how-to-enable-etcrc-local-with-systemd

Créez /etc/systemd/system/rc-local.service:

# /etc/systemd/system/rc-local.service
[Unit]
 Description=/etc/rc.local Compatibility
 ConditionPathExists=/etc/rc.local

[Service]
 Type=forking
 ExecStart=/etc/rc.local start
 TimeoutSec=0
 StandardOutput=tty
 RemainAfterExit=yes
 SysVStartPriority=99

[Install]
 WantedBy=multi-user.target

Ensuite:

sudo touch /etc/rc.local
sudo chmod +x /etc/rc.local
sudo systemctl enable rc-local

Vérifier avec:

sudo systemctl start rc-local.service
sudo systemctl status rc-local.service
Ole Tange
la source
Celui fourni par systemd StandardOutput=journal+console(la console est équivalente à tty dans votre exemple), ce qui semble être beaucoup plus utile pour le dépannage. Le support de SysVStartPriority=a également été supprimé à un moment donné. Peut-être pourriez-vous nous dire à quel point SysVStartPriority=c'est important ou le supprimer. En dehors de cela, c'est une réponse décente.
sourcejedi