redshift
のユーザレベルのサービスを書こうとしているのですが、Xorg が起動して実行されるまで待つ必要があります。現在のサービスファイルは以下のようになっています
[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
しかし、Xorgが立ち上がる前に起動しようとするようで、その後に手動でサービスを起動しなければならない。私は間違った After=
ターゲットを使っていると思います。何かヒントはありますか?
42 mkaito 2014-05-28
これについて調べてみたのですが、grawityさんの回答は古いようです。ユーザのセッションの一部として実行されるユーザサービスを systemd で設定できるようになりました。DISPLAY と XAUTHORITY を設定することができます (現在 Arch、Debian Stretch+、Ubuntu で使用されています)
これは、システムレベルのアプリ(再起動など)と同じようにプロセス管理ができるので、デスクトップのオートスタートファイルを使用するという以前の推奨事項よりも理にかなっています
今のところ最高のドキュメントは Arch wiki; Systemd/User です
TLDR version;
~/.config/systemd/user/
に目的の*.serviceファイルを作成しますsystemctl --user enable [service]
を実行します(.serviceサフィックスを除外します)- オプションで
systemctl --user start [service]
を実行して、今すぐ開始します systemctl --user status [service]
を使って様子を確認してください
他にもいくつかの便利なコマンドがあります
systemctl --user list-unit-files
– すべてのユーザーユニットを表示しますsystemctl --user daemon-reload
– .serviceファイルを編集した場合
— Later…
私はアップグレードして、ほとんどのセッションデーモンをsystemd .serviceファイルに変換しました。そこで、いくつかの追加の注意点を追加します
ログイン時にサービスを実行するためのデフォルトフックがなかったので、自分でトリガーする必要があります。私は~/.xsession
ファイルから実行しています
systemctl --user import-environment PATH DBUS_SESSION_BUS_ADDRESS
systemctl --no-block --user start xsession.target
最初の行は環境変数をsystemdユーザセッションにインポートし、2番目の行はターゲットをキックオフします。私のxsession.target
ファイル;
[Unit]
Description=Xsession running
BindsTo=graphical-session.target
私のxbindkeys.service
を例に挙げてみました
[Unit]
Description=xbindkeys
PartOf=graphical-session.target
[Service]
ExecStart=/usr/bin/xbindkeys -n -f ${HOME}/projects/dotfiles/.xbindkeysrc
Restart=always
[Install]
WantedBy=xsession.target
32 John Eikenberry 2016-09-27
通常のヒントは「しないでください」です。redshift
はシステム全体のサービスではありません – セッションごとに個別のインスタンスを持っていて、特定のセッションの Xorg に接続する方法を知る必要があります
(Xorgもシステムサービスではありません – ディスプレイマネージャだけがそうで、セッションごとに別のXorgを起動します。graphical.target
はディスプレイマネージャの準備ができたときに教えてくれますが、DM が実際にいつ最初の – あるいはすべての – ディスプレイを開始するのかについては何も書いていません)
起動時に DISPLAY=:0
で起動するだけでは十分ではありません。いつでも正確に一つのディスプレイがあるという保証はありませんし、常に :0
であるという保証もありません (例えば、古いロックファイルを残したまま Xorg がクラッシュした場合、次のロックファイルは :0
がまだ占有されていると考えて :1
で実行されるでしょう)
では、どうやって起動すればいいのでしょうか?ほとんどの場合、デスクトップ環境には、独自のセッションサービスを起動するためのいくつかの方法があります。古い投稿を参照してください
startxを使っている場合は、~/.xinitrc
を使ってそのようなものを起動することができます。スタンドアロンのウィンドウマネージャは、独自の起動/初期化スクリプトを持っていることが多いです
これらの方法に共通していることは、セッション内からプログラムが開始されるということです-上記のすべての問題を回避することができます
11 user1686 2014-05-28
以下は、私がまだ利用できないgraphical-session.target
の回避策として作成したものです(私のKubuntu 16.04システムで)
- グラフィカル-session.targetを上下に移動させる擬似的なsystemdユーザユニットを作成します
以下の内容で~/.config/systemd/user/xsession.target
を作成します
[Unit] Description = Xsession up and running BindsTo=graphical-session.target
この新しいユニットのことを systemd に伝えてください
$> systemctl --user daemon-reload
- Ubuntu 16.04デスクトップの現在利用可能なメカニックを介して
xsession.target
を制御するオートスタートとシャットダウンスクリプトを作成します
以下の内容で~/.config/autostart-scripts/xsession.target-login.sh
を作成します
#!/bin/bash if ! systemctl --user is-active xsession.target &> /dev/null then /bin/systemctl --user import-environment DISPLAY XAUTHORITY /bin/systemctl --user start xsession.target fi
以下の内容で~/.config/plasma-workspace/shutdown/xsession.target-logout.sh
を作成します
#!/bin/bash if systemctl --user is-active xsession.target &> /dev/null then /bin/systemctl --user stop xsession.target fi
スクリプトを実行可能にする
$> chmod +x ~/.config/autostart-scripts/xsession.target-login.sh $> chmod +x ~/.config/plasma-workspace/shutdown/xsession.target-logout.sh
注意: この二つのファイルは、自動起動とシャットダウンのために KDE が拾ってくる場所に置かれています。これらのファイルは他のデスクトップ環境 (例えば Gnome など) のために別の場所に置かれているかもしれませんが、それらの環境については私は知りません
注意: この回避策は複数のデスクトップセッションのサポートを欠いています。マシン上でアクティブなX11セッションが1つだけ実行されている限り、graphical-session.target
のみを正しく処理します(ただし、ほとんどのlinuxユーザにとってはこのケースが当てはまります)
graphical-session.target
に依存する独自のsystemdユーザユニットを作成し、デスクトップ上でログインしている間にクリーンに実行させることができます
例えば、@mkaitoさんのユニットはこんな感じです
[Unit] Description=Redshift PartOf=graphical-session.target [Service] ExecStart=/bin/redshift -l 28:-13 -t 5300:3300 -b 0.80:0.91 -m randr Restart=always
(ユニットを編集したらdaemon-reload
を忘れずに!)
- マシンを再起動し、ログインして、ユニットが期待通りに起動していることを確認してください
$> systemctl --user status graphical-session.target ● graphical-session.target - Current graphical user session Loaded: loaded (/usr/lib/systemd/user/graphical-session.target; static; vendor preset: enabled) Active: active since Don 2017-01-05 15:08:42 CET; 47min ago Docs: man:systemd.special(7) $> systemctl --user status your-unit...
いつかの日(Ubuntu 17.04でしょうか?)には、システムがgraphical-session.target
を正しく処理するようになるので、私の回避策は時代遅れになります。その時には、オートスタートとシャットダウンスクリプトとxsession.target
を削除してください
5 gue 2017-01-05
この解決策は、質問の筆者が質問したことを正確に実行します
Xorgが稼働するまで待つ必要があります
もっと良い方法があるかもしれませんが、すでに他のユーザーが回答しているように、これはこの問題に対する別のアプローチです
systemd の systemd-networkd-wait-online.service に似ています。このサービスに依存している他のサービスは、このサービスが正常に開始されるかタイムアウトするとすぐに起動されます
マニュアル (セクション “Files”)によると、XサーバはUNIXソケット/tmp/.X11-unix/Xn
(ここでn
は表示番号)を作成します
このソケットの存在を監視することで、特定のディスプレイのサーバが起動したことを判断することができます
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
ここで、x_server_started.service
を有効にして、エックスサーバーと同時に起動するようにします
(Xサーバの起動が必要な)他のサービスがx_server_started.service
に依存するようにした
dependent unit:
[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
エックスサーバーが問題なく起動すると、ほぼすぐにx_server_started.service
が起動し、systemdがx_server_started.service
に依存している全てのユニットの起動を進めます
3 VL-80 2018-08-22