0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

非root (一般ユーザー)での systemd ユニットファイルの編集と登録、運用

Posted at

systemd による 化は、非 root (一般ユーザー) でもできます。
改めて情報を整理しました。

まず行う事

標準では対象ユーザーのログイン中のみプロセスが起動します。これをログインせずともプロセスが起動するようにします。

loginctl enable-linger $USER

フォアグラウンドプロセスを対象にする場合のユニットファイル例

endless-loop.service.txt
[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つのメリットがあるのでオススメです。

  1. ユニットファイルを環境に応じて自動作成・配置してくれる
    • どこに配置されたかは systemctl cat の出力に書いてあります
  2. 編集終了後に 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
Raspberry Pi OS (Desktop/Bookworm) での実行例
$ 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 利用)

fastapi-webapp.service
[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 モード立ち上げ

chromium-kiosk.service
[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= 等で参照するという手もあります。

参考資料

EoT

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?