Différence entre systemd et le programme de démarrage du terminal

9

Je suis curieux de savoir quelle est cette différence entre les programmes qui le sont; démarré avec systemd lorsqu'il est activé via systemctl, par rapport à ceux démarrés via /etc/rc.localou via la CLI.

Par exemple, j'utilisais récemment shairport-sync pour le raspberry pi. Initialement, j'ai défini shairport-sync pour démarrer au moyen de sudo systemctl activé shairport-sync.

Plus tard sur la route, j'ai utilisé une fonctionnalité à l'intérieur shairport-syncpour exécuter des scripts avant et poster sur les appareils se connectant.

À ma grande surprise, les scripts lorsqu'elles sont exécutées par shairport-syncne pas kill arecordouaplay

Cependant, lorsque j'exécutais le script via un terminal, le script était exécuté et tué arecordet aplay.

Pour m'embrouiller davantage, je l'ai tué shairport-syncet démarré via le terminal pour voir la sortie de ce qui se passait. Quand je l'ai fait, les scripts ont fonctionné comme je m'y attendais lorsque l'appareil s'est connecté et tué arecordet aplay. Donc, comme j'ai désactivé fix shairport-syncdans sysmtectlet mis à fonctionner en /etc/rc.localtant que solution rapide. Après rebootça a fonctionné comme je m'y attendais.

Cela m'amène à croire qu'il existe une certaine différence entre un programme exécuté séparément systemdet un programme qui s'exécute lorsqu'il est démarré via /etc/rc.localou l'interface CLI.

Pourquoi cela arrive-t-il? Est-ce à cause de différents niveaux d'exécution? De la magie noire?

Le script exécuté lorsqu'un périphérique se connecte à shairport-syncest le suivant:shairportstart.sh

#!/bin/sh
/usr/bin/sudo /bin/pkill arecord
if [ $(date +%H) -ge "18" -o $(date +%H) -le "7" ]; then
        /usr/bin/amixer set Speaker 40%
else
        /usr/bin/amixer set Speaker 100%
fi
/home/pi/shScripts/shairportfade.sh&

exit 0

Voici le script de fondu: shairportfade.sh

#!/bin/sh
/usr/bin/amixer set Speaker 30-
for (( i=0; i<30; i++))
do  
    /usr/bin/amixer set Speaker 1+
done
exit 0

Le script exécuté lorsqu'un périphérique se déconnecte de shairport-syncest le suivant:shairportend.sh

#!/bin/sh
/usr/bin/amixer set Speaker 70%
/usr/bin/arecord -D plughw:1 -f dat | /usr/bin/aplay -D plughw:1 -f dat&
exit 0

J'ai trouvé l'erreur suivante dans le /var/log/syslogseul lorsque shairport-sync a été initialement exécuté en tant que séparé systemd. Quand a shairport-syncété exécuté à partir de la CLI ou /etc/rc.localil n'y avait aucune erreur présente.

Jan 24 00:38:45 raspberrypi shairport-sync[617]: sudo: no tty present and no askpass program specified

Veuillez noter que la seule différence réside shairport-syncdans le démarrage initial, lorsque les appareils se connectent ou se déconnectent shairport-synccontinuent de fonctionner.

Brett Reinhard
la source
1
Ce ps ... awk ... grep ...truc pourrait être remplacé par un plus simplepkill
thrig
@thrig à l'origine, la ligne était beaucoup plus simple, mais comme cela ne fonctionnait pas, j'ai pensé que j'essayais d'utiliser d'autres méthodes pour tuer l'instance qui ne fonctionnait toujours pas. Tuer le processus n'était pas le problème en soi, car il fonctionnait, mais uniquement lorsqu'il était exécuté à partir d'une connexion utilisateur
Brett Reinhard
pouvez-vous montrer la liste des /home/pi/shScripts/shairportfade.sh?
Michael D.
@MichaelD. j'ai ajouté le script de fondu ainsi que le script qui est exécuté lorsqu'un appareil se déconnecte pour shairport-sync
Brett Reinhard
@BrettReinhard quel est le problème avec l'exécution du script à partir derc.local
Michael D.

Réponses:

18

Variations de "Pourquoi les choses se comportent-elles différemment sous systemd?" sont une question fréquemment posée.

Chaque fois que quelque chose s'exécute à partir de la CLI et non à partir de systemd, il existe de grandes catégories de possibilités pour tenir compte des différences.

  1. Différentes variables d'environnement . systemddocumente les variables d'environnement qu'il transmet dans man systemd.execla section Variables d'environnement dans les processus générés . Si vous souhaitez inspecter la différence vous-même, vous pouvez l'utiliser systemd-run /path/to/binary, il exécutera votre application dans une portée transitoire, comme elle serait exécutée par un service systemd. Vous obtiendrez une sortie comme: Running as unit: run-u160.service. Vous pouvez ensuite journalctl -u run-u160.servicerevoir la sortie. Modifiez votre application pour vider les variables d'environnement qu'elle reçoit et comparez l'exécution CLI à l'exécution systemd. Si l'application n'est pas modifiée de manière pratique, vous pouvez simplement utiliser systemd-run envpour voir les variables d'environnement qui seraient transmises et examiner la journalisation du journal qui en résulte. Si vous essayez de démarrer une application graphique X11, la DISPLAYvariable d'environnement doit être définie. Dans ce cas, envisagez d'utiliser la fonction "démarrage automatique" de votre environnement de bureau au lieu de systemd.
  2. Restrictions de ressources . Voir man systemd.resource-controlpour les valeurs de configuration qui pourraient restreindre la consommation des ressources. Utilisez systemctl show your-unit-unit.servicepour vérifier les valeurs de configuration complètes affectant le service que vous essayez de démarrer.
  3. Shell non interactif . Votre bashenvironnement CLI est un shell de connexion interactif . Il a trouvé des fichiers comme .bashrccelui-là systemdnon. Outre la définition de variables d'environnement, ces scripts peuvent effectuer un certain nombre d'autres choses, telles que la connexion d'un agent SSH afin que les actions SSH ne nécessitent pas de connexion. Voir aussi Différence entre le shell de connexion et le shell sans connexion?
  4. Non ATS . Votre session interactive est connectée à un ATS que certains programmes aiment sudoet sshattendent lorsqu'ils demandent des mots de passe. Voir aussi sudo: aucun tty présent et aucun programme askpass spécifié
  5. Chemins relatifs vs absolus . Travail binaire relatif dans le shell, mais comme indiqué dansman systemd.service , le premier argument à ExecStart=doit être un chemin absolu vers un binaire.
  6. Syntaxe de ligne de commande restreinte . Les CLI Shell prennent en charge de nombreux métacaractères, tout en systemdayant une syntaxe de ligne de commande très restreinte . Selon vos besoins, vous pouvez répliquer la syntaxe Shell avec systemden exécutant explicitement votre commande via un shell:ExecStart=/bin/bash -c '/my/bash $(syntax) >/goes-here.txt'

C'est une fonctionnalité qui permet au système d'exécuter votre code dans un environnement cohérent avec des contrôles de ressources. Cela permet d'obtenir des résultats reproductibles et stables à long terme sans surcharger le matériel.

Mark Stosberg
la source
Il faut également prendre en compte le contexte MAC (SELinux, ...), les capacités, les espaces de noms ...
Bigon
2
@BrettReinhard N'appelez pas sudodans un script shell mieux exécuté sudo shairportstart.shdepuis le terminal, puisque systemd exécute le script en tant que root, pas besoin de sudo en tant que root.
Michael D.
1
J'ai résolu mon problème de plusieurs façons dans ma tentative de comprendre ce qui se passait. En fin de compte, ce que j'ai fini par faire, c'était de changer ma commande kill en /usr/bin/echo "mypassword" | /usr/bin/sudo /bin/pkill arecord. Plus tard dans la journée, j'essaierai de supprimer les commandes sudoet echode ma commande kill et de voir si cela donne les mêmes résultats. Je suppose que cela fonctionnera, car il semble que l'erreur ait été causée par l'absence de mot de passe envoyé avec la sudocommande. Merci de votre aide pour comprendre pourquoi il y a une différence entre systemdet la CLI
Brett Reinhard
1
Une autre différence, qui peut être évidente mais qui m'a mordu aujourd'hui, est que systemd essaie de suivre l'état d'un service et ne le démarre pas s'il pense qu'il est déjà actif, donc il peut même ne pas lancer de script init.d si il pense que le service fonctionne. En revanche, les scripts init.d sont généralement écrits pour toujours vérifier et essayer de démarrer le service comme il convient.
Josh Kelley
1
@JoshKelley Merci pour le conseil. Ce n'est pas une différence entre systemd et CLI mais entre les scripts systemd et sysVinit init.d.
Mark Stosberg