SandSするためのスクリプトをsystemdで自動化し、定期的に再起動できるようにします。
SandS(Space and Shift)という技術がある。スペースキーの長押しをシフトキーとして扱うもので、特にシフトキーを多用するSKKとの相性が良く、SKKユーザはたいていSandSも有効化している。
さて、このSandSを有効化する方法にはいろいろあるが、自分はxcape
とxmodmap
を併用したスクリプトを起動することでこれを行っている。この手順に関しては別途SandS memoを用意しているので参照してほしい。
しかし、この手順を実行してもxcapeの効果が切れてしまうことがあり困っていた。定期的に再起動しないといけないのが不満だったため、プロセスを自動的に再起動するようにしたい。
Systemdにはプロセスを定期的に再起動する機能があるため、これを使うことにする。
この記事では、xcape
を起動するスクリプトに若干の修正を加え、Systemdのユーザサービスとして起動し、定期的に再起動させるような設定を行う。
下準備
前述のスクリプトではxcape
がバックグラウンドで起動するようになっていたため、これをフォアグラウンドで起動するようにコマンドラインを修正する。
xcape
をフォアグラウンドで起動するには、-f
オプションを使う。
#!/bin/sh # SandS configuration if pgrep -x xcape ; then killall xcape # to prevent xcape daemon duplication fi xmodmap -e 'keycode 255=space' xmodmap -e 'keycode 65=Shift_L' env xcape -f -e '#65=space' # added -f option
スクリプトは手で起動させることもあるので、別途systemd向けに別名で保存する。今回は~/bin/sands-f.sh
とした。実行権限を忘れずに設定しておく。
% chmod u+x ~/bin/sands-f.sh
Systemd ユニットファイルの記述
Systemdはユーザモードでのサービス実行を提供している*1。今回の用途に丁度良いので、ユーザサービスとしてユニットファイルを記述する。
~/.config/systemd/user/sands.service
として以下を記述した。
[Unit] Description=Sands service [Service] # restart periodically Restart=always # alwaysは小文字なので注意すること RuntimeMaxSec=60 ExecStart=%h/bin/sands-f.sh [Install] WantedBy=default.target
ちなみに、%h
はホームディレクトリに展開される。
設定の反映と起動
% systemctl --user daemon-reload
サービスを有効化してから起動する。有効化しなければ60秒で終了したまま再起動してくれないため。
% systemd --user enable sands.service % systemd --user start sands.service
すると自動的に60秒ごとにサービスが終了してふたたび起動してくれるようになる。
ハマったところ
RuntimeMaxSec
はsystemdのバージョンが新しくないと使えないので注意すること。
Restart=always
のalways
が小文字じゃないといけない事に気付かず、全然再起動してくれないことに困ってしばらく時間が無駄になってしまった。無効な設定は警告が出ると嬉しいと思う。
今知ったけれどsystemd-analyze --user verify ユニット名
を実行するといろいろ検証してくれるようなのでこれを使えばよかった。
# 大文字のAlwaysだと警告が出る % systemd-analyze --user verify sands.service /home/windymelt/.config/systemd/user/sands.service:6: Failed to parse service restart specifier, ignoring: Always
なにかと便利そうなコマンドなので活用したい。
ちなみに今どういう設定になっているかはsystemd --user show ユニット名
したらずらっと出てくる。
systemd --user show sands.service Type=simple Restart=always NotifyAccess=none RestartUSec=100ms ... ...