web-dev-qa-db-ja.com

Xorgに依存するサービスを書く

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=ターゲットを使用していると思います。ヒントはありますか?

33
mkaito

私はこれを調査しており、Grawityの回答は時代遅れのようです。これで、ユーザーのセッションの一部として実行されるsystemdを使用してユーザーサービスをセットアップできます。 DISPLAYとXAUTHORITYを設定できます(現在ArchとDebian Stretchにあります)。

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

今のところ最高のドキュメントはArch wikiです。 Systemd/User

TLDRバージョン。

  1. ~/.config/systemd/user/に必要な* .serviceファイルを作成します
  2. systemctl --user enable [service]を実行します(.serviceサフィックスを除外します)
  3. オプションでsystemctl --user start [service]を実行して今すぐ開始
  4. systemctl --user status [service]を使用して、状態を確認します

他のいくつかの便利なコマンド。

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

-後で...

ほとんどのセッションデーモンをアップグレードしてsystemd .serviceファイルに変換しました。だから私はいくつかの追加のメモを追加できます。

ログイン時にサービスを実行するデフォルトのフックはなかったため、自分でトリガーする必要があります。私は~/.xsessionファイルからそれを行います。

systemctl --user import-environment PATH DBUS_SESSION_BUS_ADDRESS
systemctl --no-block --user start xsession.target

1行目は一部の環境変数を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
24
John Eikenberry

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

(Xorgもシステムサービスではありません。display managerのみであり、セッションごとに個別のXorgを起動します。// graphical.targetは、表示マネージャーが準備は整っていますが、DMが実際に最初の(またはすべての)ディスプレイをいつ開始するかについては何も述べていません。)

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

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

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

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

11
user1686

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

  1. pseudo systemd user unitを作成して、graphical-session.targetを上下に移動します。

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

 [Unit] 
 Description = Xsession up and running 
 BindsTo = graphical-session.target 

この新しいユニットについてsystemdに伝えます。

$> systemctl --user daemon-reload
  1. 現在作成されているUbuntu 16.04デスクトップのメカニズムを介してxsession.targetを制御するautostartおよびshutdownスクリプトを作成します。

次の内容で~/.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-ユーザーが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-ユーザーは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など)の別の場所に配置されている可能性がありますが、それらの環境については知りません。

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

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

例として、@ 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を忘れずに!)

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

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

5
gue

このソリューションは、質問の作成者が要求することを正確に実行します。

xorgが稼働するまで待つ必要があります

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

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

manual (セクション「ファイル」)に従って、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サーバーの起動が必要)が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に依存するすべてのユニットを起動します。

3
VL-80