systemd上でxrandrが動かないのを解決した回
目的
systemd上でXアプリケーションを動作させる。
理由
Manjaro Linuxではモニターを繋いだだけでは自動でマルチモニタにならないため。マルチモニタを使う場合は xrandr を用いて
xrandr --output LVDS1 --auto --primary --output VGA1 --auto --above LVDS1
といったコマンドをいちいち打つ必要がある。面倒なのでコマンドをシェルスクリプトにしてモニターを繋ぐたびに手動でシェルスクリプトを実行していたが、ぶっちゃけめんどくさくなってきたので自動化しようと考えた。
提案手法
同じようなことを考えることはいるもので、下記のようにタイマー機能で1秒ごとにスクリプトを実行して切り替えを自動化している人がいることがわかった。
ArchLinuxで自動でdisplayの接続を認識し調整する
上記のページはウィンドウマネージャーとして awesome 環境を用いているが、自分は Xfce なので cron か systemd を検討した。自分の環境に cron はインストールしていないので環境を汚したくないなと思って systemd で自動化することに決めた。
systemd での自動実行には systemd.timer を用いればできることがわかったので、これについて調べた。
systemd.timer について
ざっくりと言えば、<サービス名>.service と同じディレクトリに <サービス名>.timer を置いてやればいい。
systemctl daemon-reload も念の為忘れずに。
.service と .timer を書いた
autodualmonitor.service
[Unit] Description = Automatic dual-single monitor switcher [Service] Type = oneshot ExecStart = /home/<ユーザー名>/MyShellScript/auto_dualmonitor.sh Requires=lightdm.service
autodualmonitor.timer
[Unit] Description=Automatic dual-single monitor switcher : timer [Timer] OnBootSec=1min OnUnitActiveSec=1sec [Install] WantedBy=timers.target
両方とも /etc/systemd/system ディレクトリに配置した。スクリプトは上記の ExecStart に書かれている通りの場所に配置した。
トラブルシューティング
systemctl daemon-reload
してから動くか試すために
sudo systemctl start autodualmonitor.service
を実行したがエラーが出て動作しなかった。 .timer もenableにしてみたが Active: failed (Result: exit-code) になっており、正常に動作していないことがわかった。
systemctl status autodualmonitor.service
でログを見てみたところ、 Can't open screen というログが見られた。どうやら xrandr が動いていないようだ。
調べてみたところ、Archlinux wiki の次のページに答えがあった。
DISPLAY は X アプリケーションがどのディスプレイを使えばいいのか知るために使用されます。XAUTHORITY はユーザーの .Xauthority ファイルのパスと、X サーバーにアクセスするのに必要な cookie を指定します。systemd ユニットから X アプリケーションを起動する場合、これらの変数を設定する必要があります。バージョン 219 から、セッションが開始したときに DISPLAY と XAUTHORITY を systemd --user デーモンの環境にアップロードする X11 セッションアプレット /etc/X11/xinit/xinitrc.d/50-systemd-user.sh が systemd に付属するようになりました。これによって、X を標準の方法で起動しているかぎり、ユーザーサービスは DISPLAY や XAUTHORITY を使用することができるようになっています。<<
要約するに、DISPLAYとXAUTHORITYの環境変数が設定されていないとxrandrのようなXアプリケーションは動作しないということらしい。で、ターミナルから実行して動作するのに systemd では何故動作しないのかといえば、
ということだった。つまりはシェルスクリプト内でDISPLAYとXAUTHORITYを設定してやれば動作すると見ていいだろう。そこで autodualmonitor.sh(モニター切り替え用のスクリプト) を次のように書き換えた。
autodualmonitor.sh
#!/bin/bash IN="LVDS1" EXT="VGA1" export DISPLAY=:0.0 export XAUTHORITY="/home/<ユーザー名>/.Xauthority" if (xrandr | grep "$EXT disconnected"); then xrandr --output $IN --auto $EXT --off else xrandr --output $IN --auto --primary --output $EXT --auto --above $IN fi
大抵の場合、DISPLAYは:0.0なので特に考えずにそのまま書いた。XAUTHORITYは echo $XAUTHORITY を実行して調べてきたものをそのまま書いた。
書き換えてから念の為 sudo systemctl daemon-reload し、systemctl start autodualmonitor.service がエラーを出さないことを確認してからPCを再起動した。
再起動後に systemctl status autodualmonitor.timer を実行して見てみると Active: active (waiting) となっており、モニターを抜き差ししてみると、少し時間を置いてモニターが接続されることが確認できた。