Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

SandS(スペースキーをシフトキーにする)をsystemdで起動して再起動を自動化する / systemd-analyzeでユニットファイルを検証する

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

atani.github.io

なにかと便利そうなコマンドなので活用したい。

ちなみに今どういう設定になっているかはsystemd --user show ユニット名したらずらっと出てくる。

systemd --user show sands.service
Type=simple
Restart=always
NotifyAccess=none
RestartUSec=100ms
...
...
★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?