Xorgに依存するサービスの作成


30

のユーザーレベルのサービスを作成しようとしていますが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=ターゲットを使用していると思います。ヒントはありますか?

回答:


20

私はこれを調査してきましたが、grawityの答えは時代遅れのようです。ユーザーのセッションの一部として実行されるsystemdでユーザーサービスを設定できるようになりました。DISPLAYとXAUTHORITYを設定できます(現在はArchとDebian Stretchで)。

これは、デスクトップレベルの自動起動ファイルを使用するという以前の推奨事項よりも理にかなっています。システムレベルのアプリ(再起動など)と同じようにプロセス管理を取得できます。

現時点で最高のドキュメントはArch wikiです。システム/ユーザー

TLDRバージョン。

  1. 目的の* .serviceファイルを作成します ~/.config/systemd/user/
  2. 実行systemctl --user enable [service](.serviceサフィックスを除外)
  3. オプションで実行systemctl --user start [service]して今すぐ開始
  4. 使用systemctl --user status [service]方法

その他の便利なコマンドがいくつかあります。

  • systemctl --user list-unit-files -すべてのユーザーユニットを表示
  • s ystemctl --user daemon-reload-.serviceファイルを編集する場合

-後で...

ほとんどのセッションデーモンをアップグレードして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

2
ユニットファイルの例を提供し、ユニットでDISPLAYおよびXAUTHORITYを使用できるようにする方法を説明できる場合は、受け入れられた回答を変更させていただきます。
mkaito

@mkaito DebianがStretchをリリースしたら、それについて調べます。私はDebianの安定版を実行していますが、それまでそれを使って遊ぶのを待っていました。
ジョンエイケンベリー

@mkaitoでgithub.com/systemd/systemd/blob/v219/NEWS#L194は、それがアンX11セッションスクリプトレットは、現在出荷されています」と言うことのアップロード$ DISPLAYとの環境に$ XAUTHORITYにsystemd --userデーモンのセッションが開始されます。これにより、systemdユーザーサービスとして実行されるX11対応アプリケーションとの互換性が向上するはずです。」
ジョシュ

特別なものが必要かどうかを明確にするために、ユニットファイルの例を引き続き見たいと思います。
mkaito

11

通常のヒントは「しない」です。 redshiftシステム全体のサービスではありません。各セッションに個別のインスタンスがあり、特定のセッションのXorgに接続する方法を知る必要があります。

(Xorgもシステムサービスではありません。ディスプレイマネージャーのみです。また、セッションごとに個別のXorgを起動しgraphical.targetます。最初-またはすべて-が表示されます。)

起動時に起動するDISPLAY=:0だけでは十分ではありません。特定の時間にディスプレイが1つだけであるという保証はなく、常にそうであるという保証もありません:0(たとえば、Xorgがクラッシュして古いロックファイルを残した場合、次のディスプレイがそのまま実行さ:1れます):0まだ占有されていると思います); XAUTHORITYX11では認証が必要なので、ファイルへのパスも設定する必要があります。redshiftログアウトして再度ログインする場合は必ず再起動してください。

それで、それを始める方法は?ほとんどの場合、デスクトップ環境には、独自のセッションサービスを開始するいくつかの方法があります。2つの通常のものを既に説明している古い投稿参照してください~/.xprofileスクリプトと~/.config/autostart/*.desktop場所。

startxを使用すると、~/.xinitrcそのようなことを開始するために使用できます。スタンドアロンのウィンドウマネージャには、多くの場合、独自の起動/初期化スクリプトがあります。例えば~/.config/openbox/autostartこのOpenBoxため。

これらすべての方法に共通しているのは、プログラムがセッションから開始されることです。上記のすべての問題を回避します。


多くの場合、redshiftはシステム全体のサービスではありませんが、OPがやろうとしているのはまさにユーザーサービスであることです。
simotek

5

graphical-session.targetこれは、まだ利用できない(Kubuntu 16.04システムで)回避策として作成したものです。

  1. グラフィカルなsession.targetを上下させる擬似systemdユーザーユニットを作成します。

~/.config/systemd/user/xsession.target次の内容で作成します。

[単位]
説明= Xsessionが稼働中
BindsTo = graphical-session.target

systemdにこの新しいユニットについて教えてください:

$> systemctl --user daemon-reload
  1. Ubuntu 16.04デスクトップの現在利用可能なメカニズムを制御する自動起動およびシャットダウンスクリプトを作成しxsession.targetます。

~/.config/autostart-scripts/xsession.target-login.sh次の内容で作成します。

#!/ bin / bash

もし!systemctl --user is-active xsession.target&> / dev / null
それから
  / 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
それから
  / 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

注:これら2つのファイルは、KDEが自動起動およびシャットダウンのためにそれらを選択する場所に配置されます。ファイルは他のデスクトップ環境の別の場所(Gnomeなど)に配置されている可能性がありますが、それらの環境については知りません。

注:この回避策には、マルチデスクトップセッションのサポートがありません。graphical-session.targetマシン上で実行されているアクティブなX11セッションが1つだけである限り、正しく処理するだけです(ただし、ほとんどのLinuxユーザーがそうです)。

  1. 依存し、デスクトップにログインしている間、それらをきれいに実行する独自のsystemdユーザーユニットを作成しますgraphical-session.target

例として、@ mkaitoのユニットは次のようになります。

[単位]
Description = Redshift
PartOf = graphical-session.target

[サービス]
ExecStart = / bin / redshift -l 28:-13 -t 5300:3300 -b 0.80:0.91 -m randr
再起動=常に

daemon-reloadユニットを編集した後にを行うことを忘れないでください!)

  1. マシンを再起動し、ログインしてユニットが期待どおりに起動することを確認します
$> systemctl --user statusグラフィカルセッション。ターゲット
●graphic-session.target-現在のグラフィカルユーザーセッション
   ロード済み:ロード済み(/usr/lib/systemd/user/graphical-session.target; static;ベンダープリセット:有効)
   アクティブ:ドン2017-01-05 15:08:42 CET以降アクティブ 47分前
     ドキュメント:man:systemd.special(7)
$> systemctl --user status your-unit ...

将来のある日(Ubuntu 17.04になりますか?)、システムはgraphical-session.targetそれ自体を正しく処理するため、私の回避策は廃止されます。その日は、自動起動スクリプトとシャットダウンスクリプトを削除するだけでなくxsession.target、カスタムユーザーユニットが変更されずにそのまま動作する場合もあります。


私はこれが古いコメントであることを知っていますが、ワークスペース>起動とシャットダウン>自動起動の下にあるシステム設定アプリから起動/ログインスクリプトを追加することもできます。
AmbientCyan

2

このソリューションは、質問の作成者が尋ねるとおりに実行します。

Xorgが起動して実行されるまで待つ必要があります

他のユーザーが既に回答しているように、より良い方法がありますが、これはこの問題に対する別のアプローチです。

特定の基準が満たされるまでブロックするsystemdのsystemd-networkd-wait-online.serviceに似ています。それに依存する他のサービスは、このサービスが正常に開始またはタイムアウトするとすぐに起動されます。

パーマニュアル(セクション「ファイル」)、XサーバはUNIXソケットを作成します/tmp/.X11-unix/Xnnディスプレイ番号です)。

このソケットの存在を監視することにより、特定のディスプレイのサーバーが起動したことを判断できます。

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.serviceXサーバーと同時に起動できるようにします。

依存する他のサービス(Xサーバーを起動する必要がある)を作成する x_server_started.service

従属ユニット:

[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サーバーが問題なく起動した場合、x_server_started.serviceほとんどすぐに起動し、systemdはに依存するすべてのユニットを起動しx_server_started.serviceます。


これはうまく機能します。余分なサービスはいい感じです。ターゲットサービスでExecStartPreを使用することもできます。ただし、「exit 0」の前に余分な「sleep 1」を追加する必要がありました。ただ、Xをすぐにキャッチして捕まえるには少し速すぎたようです。
TTimo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.