J'essaie d'écrire un service de niveau utilisateur pour redshift
et il doit attendre que Xorg soit opérationnel. Mon fichier de service actuel ressemble à ceci:
[Unit]
Description=Redshift
After=graphical.target
[Service]
Environment=DISPLAY=:0
ExecStart=/bin/redshift -l 28:-13 -t 5300:3300 -b 0.80:0.91 -m randr
Restart=always
[Install]
WantedBy=default.target
Cependant, il semble qu'il tente de démarrer avant que Xorg ne soit opérationnel et je dois ensuite démarrer le service manuellement. Je suppose que j'utilise la mauvaise cible After=
. Des allusions?
J'ai étudié cela et la réponse de Grawity semble obsolète. Vous pouvez maintenant configurer les services utilisateur avec systemd qui s’exécute avec la session de l’utilisateur. Ils peuvent avoir les options DISPLAY et XAUTHORITY (actuellement dans Arch et Debian Stretch).
Cela a du sens par rapport aux recommandations précédentes consistant à utiliser des fichiers à démarrage automatique sur le bureau, car vous bénéficiez d'une gestion des processus identique à celle d'une application système (redémarrage, etc.).
Le meilleur documentaire actuellement est le wiki Arch; Systemd/User
Version TLDR;
~/.config/systemd/user/
systemctl --user enable [service]
(exclure le suffixe .service)systemctl --user start [service]
pour commencer maintenantsystemctl --user status [service]
pour vérifier comment ça se passeQuelques autres commandes utiles.
systemctl --user list-unit-files
- voir toutes les unités utilisateurystemctl --user daemon-reload
- si vous éditez un fichier .service-- Plus tard...
J'ai mis à niveau et converti la plupart de mes démons de session en fichiers systemd .service. Je peux donc ajouter quelques notes supplémentaires.
Il n'y avait pas de hook par défaut pour exécuter les services lors de la connexion, vous devez donc le déclencher vous-même. Je le fais à partir de mon fichier ~/.xsession.
systemctl --user import-environment PATH DBUS_SESSION_BUS_ADDRESS
systemctl --no-block --user start xsession.target
La première ligne importe certaines variables d’environnement dans la session utilisateur systemd et la seconde lance la cible. Mon fichier xsession.target;
[Unit]
Description=Xsession running
BindsTo=graphical-session.target
Mon xbindkeys.service à titre d'exemple.
[Unit]
Description=xbindkeys
PartOf=graphical-session.target
[Service]
ExecStart=/usr/bin/xbindkeys -n -f ${HOME}/projects/dotfiles/.xbindkeysrc
Restart=always
[Install]
WantedBy=xsession.target
L'indice habituel est "ne pas". redshift
n'est pas un service à l'échelle du système - il aurait une instance distincte pour chaque session , et il a besoin de savoir comment se connecter à Xorg de cette session.
(Xorg n'est pas non plus un service système - seul le gestionnaire d'affichage l'est, et il lance également un Xorg distinct pour chaque session. // graphical.target
vous indiquera quand le gestionnaire d'affichage est prêt, mais cela ne dit rien sur le moment où le DM commence réellement le premier ou tous les affichages.)
Il ne suffit pas de le démarrer au démarrage avec DISPLAY=:0
, car rien ne garantit qu’il y ait exactement un affichage à la fois, ni qu’il reste toujours :0
(par exemple, si Xorg se bloque en laissant un fichier de verrouillage obsolète, le prochain s'exécutera à :1
car il penserait que :0
est toujours occupé); vous devez également définir le chemin d'accès à votre fichier XAUTHORITY
, car X11 requiert une authentification; et assurez-vous que redshift
est redémarré si vous vous déconnectez et vous reconnectez.
Alors, comment le démarrer? L'environnement de bureau dispose presque toujours de plusieurs méthodes pour démarrer ses propres services de session . Voir un article plus ancien qui décrit déjà les deux messages habituels; le script ~/.xprofile
et l'emplacement ~/.config/autostart/*.desktop
.
Si vous utilisez startx , vous pouvez utiliser ~/.xinitrc
pour démarrer de telles choses. Les gestionnaires de fenêtres autonomes ont souvent leurs propres scripts de démarrage/init. par exemple. ~/.config/openbox/autostart
pour Openbox.
Le point commun à toutes ces méthodes est que le programme est lancé à partir de dans la session, ce qui évite tous les problèmes énumérés ci-dessus.
Voici ce que je viens de créer comme solution de contournement au graphical-session.target
pas encore disponible (Sur mon système Kubuntu 16.04):
Créez ~/.config/systemd/user/xsession.target
avec le contenu suivant:
[Unité] Description = Xsession en marche BindsTo = graphical-session.target
Parlez de cette nouvelle unité à systemd:
$> systemctl --user daemon-reload
xsession.target
via les mécanismes actuellement disponibles du bureau Ubuntu 16.04.Créez ~/.config/autostart-scripts/xsession.target-login.sh
avec le contenu suivant:
#!/bin/bash if! systemctl --user is-active xsession.target &> /dev/null then /bin/systemctl --user import-environment AFFICHER XAUTHORITY /bin/systemctl - utilisateur start xsession.target fi
Créez ~/.config/plasma-workspace/shutdown/xsession.target-logout.sh
avec le contenu suivant:
#!/bin/bash si systemctl --user est actif xsession.target &> /dev/null then /bin/systemctl - arrêt utilisateur xsession.target fi
Rendre les scripts exécutables:
$> chmod + x ~/.config/autostart-scripts/xsession.target-login.sh $> chmod + x ~/.config/plasma-workspace/shutdown/xsession.target -logout.sh
Remarque: ces deux fichiers sont placés à l'emplacement où KDE les récupérera pour un démarrage automatique et un arrêt. Les fichiers peuvent être placés ailleurs pour d'autres environnements de bureau (par exemple, Gnome), mais je ne connais pas ces environnements.
Remarque: Cette solution de contournement ne prend pas en charge les sessions multi-postes de travail. Il ne gère correctement le graphical-session.target
que si une seule session X11 active est exécutée sur une machine (mais c'est le cas pour la plupart des utilisateurs de Linux nous-mêmes).
graphical-session.target
et faites-les fonctionner correctement tout en étant connecté à votre bureau.Comme exemple, l'unité de @ mkaito devrait ressembler à ceci:
[Unité] Description = Redshift PartOf = graphical-session.target [Service] ExecStart =/bin/redshift -l 28 : -13 -t 5300: 3300 -b 0,80: 0,91 m randr Redémarrer = toujours
(N'oubliez pas de faire un daemon-reload
après avoir modifié vos unités!)
$> systemctl - statut de l'utilisateur graphical-session.target ● graphical-session.target - Session graphique actuelle Loaded: chargé (/ usr/lib/systemd/user /graphical-session.target; statique; préréglage du vendeur: activé) Actif: actif depuis Don 2017-01-05 15:08:42 CET; Il y a 47 minutes Docs: man: systemd.special (7) $> Systemctl - statut de l'utilisateur your-unit ...
À un moment donné (ce sera Ubuntu 17.04?), Ma solution de contournement devient obsolète, car le système gérera le graphical-session.target
correctement. À cette date, supprimez simplement le script de démarrage automatique et d'arrêt ainsi que le xsession.target
- vos unités utilisateur personnalisées peuvent rester intactes et fonctionner.
Cette solution fait exactement ce que l'auteur de la question demande:
il doit attendre que Xorg soit opérationnel
Bien qu'il puisse y avoir de meilleures façons de le faire, comme d'autres utilisateurs l'ont déjà répondu, c'est une autre approche de ce problème.
Il est similaire au service systemd systemd-networkd-wait-online.service qui bloque jusqu'à ce que certains critères soient remplis. Les autres services qui en dépendent seront lancés dès que ce service démarrera avec succès ou expirera.
Selon le manuel (section "Fichiers"), le serveur X crée un socket UNIX /tmp/.X11-unix/Xn
(où n
est un numéro d'affichage).
En surveillant la présence de ce socket, nous pouvons déterminer que le serveur pour un affichage particulier a démarré.
confirm_x_started.sh
:
#!/bin/bash
COUNTER=0
while [ 1 ]
do
# Check whether or not socket exists
if [ -S /tmp/.X11-unix/X0 ]
then
exit 0
fi
((++COUNTER))
if [ $COUNTER -gt 20 ]
then
exit 1
fi
sleep 0.5
done
x_server_started.service
:
[Unit]
Description=Monitor X server start
[Service]
Type=oneshot
ExecStart=/path/to/confirm_x_started.sh
[Install]
WantedBy=example.target
Activez maintenant x_server_started.service
pour démarrer en même temps avec le serveur X.
Faire en sorte que les autres services (nécessitant le démarrage du serveur X) dépendent de x_server_started.service
unité dépendante:
[Unit]
Description=Service that needs to have the X server started
Requires=x_server_started.service
After=x_server_started.service
[Service]
ExecStart=/path/to/binary
[Install]
WantedBy=example.target
Si le serveur X démarre sans problème, le x_server_started.service
démarre presque immédiatement et systemd démarrera toutes les unités dépendantes de x_server_started.service
.