システム設定イベントで表示関連命令を実行する

システム設定イベントで表示関連命令を実行する

アップストリームを共有したいsystemd / udev設定を開発していますが、ハッキングされていない方法で動作させることはできません。デフォルトでは、私はこのスクリプトをsystemdサービスの実行者として使用します。

      ICON="somepath/dslr-camera-white.png"

      function on-display() {
          local sdisplay=$(echo $XDG_SESSION_TYPE)
          if [ "$sdisplay" == "wayland" ]; then
          local display=":$(echo $WAYLAND_DISPLAY)"
          else
          local display=":$(ls /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)"
          fi
          
          local user=$(who | grep '('$display')' | awk '{print $1}' | head -n 1)

          local uid=$(id -u $user)

          sudo -u $user DISPLAY=$display DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$uid/bus "$@"
      }

      cleanup() {
          on-display notify-send -i $ICON "Disconnected" "The DSLR Camera has been turned off." --app-name="DSLR Webcam"
          trap - SIGTERM && kill -- -$$
      }

      trap cleanup SIGINT SIGTERM EXIT

      on-display notify-send -i $ICON "Connected" "The DSLR Camera has been turned on and it is ready to use." --app-name="DSLR Webcam"
      on-display yad --window-icon=$ICON --image=$ICON --no-buttons --title="DSLR Webcam" --notification --listen &

      output=$(v4l2-ctl --list-devices)
      line=$(echo "$output" | grep "Virtual Camera")
      vdevice=$(echo "$output" | sed -n "/$line/{n;s/^\t\+//p;}")
      gphoto2 --stdout --capture-movie | ffmpeg -i - -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 $vdevice

サービスのポイントは、特定のgphoto2対応カメラが接続されているときにudevルールによって開始されることであるため、次のudevルールがあります。

ACTION=="add", ATTR{idVendor}=="04a9", ATTR{idProduct}=="3218", RUN+="systemctl start dslr-webcam.service"
ACTION=="remove", ATTR{idVendor}=="04a9", ATTR{idProduct}=="3218", RUN+="systemctl stop dslr-webcam.service"

これまでsystemdサービスを使用するための代替案を読んだので、「いいね」ですRUN。しかし、とにかく... ここで質問は具体的にyad

yadこれはCLIでダイアログボックスを表示できるプログラムです。カメラがアクティブになったときにシステムアイコンを表示したいので、システムアイコンを作成するために使用しました。

質問

とは異なり、notify-send一部の通常のソケットで動作する可能性があり、動作するにはyad適切な設定が必要です。XAUTHORITYそれ以外の場合。cannot open display: :0私の場合、ハッキーソリューションはSDDM(ディスプレイマネージャ)を使用しているので、/tmpスクリプトに追加できるようにディレクトリに常駐するので、正しいXauthorityに設定するだけでした。

XAUTHORITY=$(ls /tmp/xauth*)

それから効果がありましたが…ひどいです。多くの仮定をし、実際に全体の機能on-displayも悪い考えのように見えました。これを別のシステムにインポートすると、適切なXauthorityが数え切れないほど多くの場所にいる可能性があり、まだWaylandを試したことがないので、おそらく動作しません(後で残します)。

何についてxauth

どういうわけか正しいXauthorityを検索できると思いましたが、そうではありませんxauth...このスクリプトはシステムサービスなので、戻ってxauth info正しいAuthority file: /root/.xauthWV7OfUユーザーとして実行しましたが、sudo -u $user xauth info動作Authority file: /home/myuser/.Xauthorityしません。役割は与えられると与えられますyad。正しい役割はXAUTHORITYディスプレイマネージャによって設定されるため、子プロセスからのみインポートできるようです。

私もthisが提供するすべての方法を試しました。回答ところで、最初のものはXAUTHORITY実際にはシステム環境ではないので動作しません/run/sddm/xauth_KvyuHd。それはうまくいくので、xauthファイルとは異なります。/tmp/xauth_FzoQqz

前の質問と同じ質問から出ました。これこの方法は効果があるようですが、移植性がどれほど良いかはわかりません。そしてまだ陳腐に見えます。


ユーザーサービスとして実行

おそらく、これはユーザーとして実行されるのを防ぐスクリプトには何もないので、最も有望なものかもしれません(それも削除しましたon-display)。私はこれを試しましたが、カメラが接続されていて実行するとsystemctl --user start dslr-webcam.service期待どおりに動作します(含むyad)、今ルールに関する質問がありますudev。を含むいくつかの場所を検索しました。ここただし、ルールでシステムユーザーサービスを実行する方法が見つかりません。どのユーザーを使用するのか、udevどうすればわかりますか?udev

ベストアンサー1

代わりに、udevルールから直接ユーザーサービスを実行しないでください。udevがデバイスに特定のユーザーサービスが必要であることをsystemdに通知します。ランニング。

このようにTAG+="systemd", ENV{SYSTEMD_USER_WANTS}="dslr-webcam.service"

ACTION=="add", ATTR{idVendor}=="04a9", ATTR{idProduct}=="3218". TAG+="systemd", ENV{SYSTEMD_USER_WANTS}="dslr-webcam.service"
ACTION=="remove", ATTR{idVendor}=="04a9", ATTR{idProduct}=="3218", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}="dslr-webcam.service"

GUIアクセスが必要なので、それ自体とdslr-webcam.service宣言する必要があります。このように宣言されると、サービスは自動的に正しいDISPLAY変数とXAUTHORITY変数を取得する必要があります。BindsTo=graphical-session.targetAfter=graphical-session.target

さて、あなたのアイデアを共有していただきありがとうございます。それは私に非常に似たものを作ることができるインスピレーションを与えました...

おすすめ記事