systemd による 化は、非 root (一般ユーザー) でもできます。
改めて情報を整理しました。
まず行う事
標準では対象ユーザーのログイン中のみプロセスが起動します。これをログインせずともプロセスが起動するようにします。
loginctl enable-linger $USER
フォアグラウンドプロセスを対象にする場合のユニットファイル例
[Unit]
Description=Endless loop (User)
After=default.target
Requires=default.target
[Service]
Type=simple
ExecStart=/bin/bash -c "while true ; do date ; sleep 3 ; done"
Restart=always
[Install]
WantedBy=default.target
インストール
cat endless-loop.service.txt | SYSTEMD_EDITOR=tee systemctl --user edit --full --force endless-loop.service
edit
を使うと2つのメリットがあるのでオススメです。
- ユニットファイルを環境に応じて自動作成・配置してくれる
- どこに配置されたかは
systemctl cat
の出力に書いてあります
- どこに配置されたかは
- 編集終了後に
daemon-reload
を自動で行ってくれる
あとは OS 起動時に自動起動するようにします。
systemctl --user enable endless-loop.service
他のスクリプトから起動する等、自動起動が不要であれば disable
しておき、手動で start
します。
systemctl --user disable endless-loop.service
## 手動起動
systemctl --user start endless-loop.service
After= や Requires= 等で参照できるtargetの一覧の取得方法
systemctl --user list-unit-files --type=target
$ systemctl --user list-unit-files --type=target
UNIT FILE STATE PRESET
basic.target static -
bluetooth.target static -
default.target static -
exit.target static -
graphical-session-pre.target static -
graphical-session.target static -
paths.target static -
printer.target static -
shutdown.target static -
smartcard.target static -
sockets.target static -
sound.target static -
timers.target static -
xdg-desktop-autostart.target static -
意味や効果は man systemd.special
をご覧ください。
この中で使えそうなのはこのあたりでしょうか。
- 起動後:
default.target
- Web サーバー等の待ち受けに使える
- GUI ログイン後:
graphical-session.target
- キオスク端末化に使える
サンプル
※ ほぼ自分用ですが、お役に立てば。
FastAPI の立ち上げ (mise 利用)
[Unit]
Description=FastAPI application with uvicorn
[Service]
Type=simple
WorkingDirectory=%h/fastapi_app1
ExecStart=%h/.local/bin/mise exec python -- uvicorn run:app --host 127.0.0.1 --port 8000
Restart=always
RestartSec=3
Environment=PYTHONUNBUFFERED=1
Environment=UVICORN_CMD_COLOR=false
[Install]
WantedBy=default.target
Chromium の KIOSK モード立ち上げ
[Unit]
Description=Chromium Kiosk Mode on Wayland+Labwc (User)
After=graphical-session.target
Requires=graphical-session.target
[Service]
Type=simple
ExecStart=/usr/bin/chromium-browser --noerrdialogs --disable-infobars --no-first-run --enable-features=OverlayScrollbar --start-maximized --ozone-platform=wayland --disable-features=Translate --incognito --remote-debugging-port=9222 --kiosk "https://example.com"
Restart=always
Environment=XDG_RUNTIME_DIR=%t
Environment=WAYLAND_DISPLAY=wayland-0
[Install]
WantedBy=default.target
※ After=
を graphical-session.target
から fastapi-webapp.service
に変えれば、FastAPI の起動後に chromium-browser が起動します
ログ確認 (journalctl)
journalctl
の --user
や -u
でログ表示が意図通りにできない場合は、他のオプションを使ってみてください。
journalctl _SYSTEMD_USER_UNIT=endless-loop.service
journalctl _UID=$(id -u)
以下のように補完が効く(ハズ)ので、忘れても安心かなと。
$ journalctl _<TAB>
_AUDIT_LOGINUID= _GID= _SOURCE_MONOTONIC_TIMESTAMP= _SYSTEMD_UNIT=
_AUDIT_SESSION= _HOSTNAME= _SOURCE_REALTIME_TIMESTAMP= _SYSTEMD_USER_SLICE=
_BOOT_ID= _KERNEL_DEVICE= _STREAM_ID= _SYSTEMD_USER_UNIT=
_CAP_EFFECTIVE= _KERNEL_SUBSYSTEM= _SYSTEMD_CGROUP= _TRANSPORT=
_CMDLINE= _MACHINE_ID= _SYSTEMD_INVOCATION_ID= _UDEV_DEVNODE=
_COMM= _PID= _SYSTEMD_OWNER_UID= _UDEV_SYSNAME=
_EXE= _RUNTIME_SCOPE= _SYSTEMD_SLICE= _UID=
$ journalctl _SYSTEMD_<TAB>
_SYSTEMD_CGROUP= _SYSTEMD_OWNER_UID= _SYSTEMD_UNIT= _SYSTEMD_USER_UNIT=
_SYSTEMD_INVOCATION_ID= _SYSTEMD_SLICE= _SYSTEMD_USER_SLICE=
他サービスの起動まで待つ (PreExecStart= 利用)
他サービスの立ち上がりを待ちたい時に使えます。同じユーザー内であれば After=
といった依存関係が使えますが、root 等の他ユーザーの参照はできませんし、外部サービスの場合は困ります。
PreExecStart=
は 終了コードが 0 以外の時は繰り返し実行されるので、ヘルスチェックコマンドを入れられます。
http://127.0.0.1:8000/api
の 200 番台返却をチェックする例です。
[Service]
ExecStartPre=/bin/bash -c 'for i in {1..30}; do curl --fail --max-time 3 http://127.0.0.1:8000/api && exit 0 || sleep 1; done; exit'
ping の例です。
[Service]
ExecStartPre=/bin/bash -c 'for i in {1..30}; do ping -c 1 HOST && exit 0 || sleep 1; done; exit 1'
内容が複雑になるならスクリプト化したり、 Type=oneshot
のユニットを作成して、それを After=
等で参照するという手もあります。
参考資料
- サーバー起動時に非rootユーザーでsystemdを使ってサービスを立ち上げる
- systemdのUnitファイルのパスを知らなくともUnitファイルを編集する方法
- OS起動時にsystemdで行われていること
- systemd.unit — Unit configuration
- systemdのunitファイル(service)でmiseを使う方法
EoT