DeveloperWiki:Systemd

提供: ArchWiki
ナビゲーションに移動 検索に移動

このページは計画のためのものです。

パッケージ化メモ

ユニット

  • 存在するときはいつでもアップストリームのユニットファイルを使う
  • Arch 固有のことをしないようにする。これは将来アップストリームがユニットファイルを提供するようになった後に、動作を変更しない可能性を最大化します。特に EnvironmentFile= は、Arch 固有の /etc/conf.d を指しているときは特に避けるようにしてください
  • 常に初期化の動作と実際のデーモンの動作を分ける。必要であれば、初期化のために別のユニットファイルを使って、systemd.unit(5) の ConditionFoo によりブロックされるようにしてください。このような例は sshd.servicesshdgenkeys.service があります。

以下の場合には EnvironmentFile= を使わなくて構いません。

  • デーモンが、同じ設定を指定できる設定ファイルを持っている
  • デフォルトのサービスファイルがほとんどの一般的なケースで "そのまま動く" 場合。動作を変えたいユーザーはこの場合デフォルトのサービスファイルをオーバーライドする必要があります。適切なデフォルトサービスファイルを提供することが不可能な場合は、ケースバイケースの方針で議論する必要があります

以下はサービスファイルに関するいくつかのコメントで、現在の動作を大まかに維持して、変な動作を避けることが前提です。

  • サービスの開始前にネットワークが設定されている必要があるときは、After=network.target を使ってください。Wants=network.targetRequires=network.target使わない でください
  • 必要でないと分かっているとき以外は Type=forking を使ってください
    • たくさんのデーモンが、始めのプロセスの終了を準備ができたことを知らせるために使います。問題を最小化するため、このモードを使うと一番安全です
    • どのプロセスがメインのプロセスか systemd が確実に理解できるように、デーモンに pidfile を生成させて、systemd に PIDFile= を使って pidfile を指し示してください
    • そのデーモンが dbus により有効化される・socket により有効化される・明示的に Type=notify をサポートしている、のいずれかの場合、話は変わってきますが、現在は少数のデーモンにのみ当てはまります
  • Arch の rc スクリプトは依存関係をサポートしていませんが、systemd においては必要に応じて追加される必要があります
    • 一番一般的なケースは、 A が開始する前にサービス B が起動している必要がある、という場合です。このケースでは ARequires=BAfter=B を追加してください。
    • 依存が任意の場合、代わりに Wants=BAfter=B を追加してください
    • 依存は通常サービスに置かれ、依存先には置かれません。違ったことをしたくなった場合、何をしようとしているか知っておく必要があります。

単純な慣習の例

rc script
#!/bin/bash

. /etc/rc.conf
. /etc/rc.d/functions

case "$1" in
  start)
    stat_busy "Starting NIS Server"
    /usr/sbin/ypserv
    if [ $? -gt 0 ]; then
      stat_fail
    else
      add_daemon ypserv
      stat_done
    fi
    ;;
  stop)
    stat_busy "Stopping NIS Server"
    killall -q /usr/sbin/ypserv
    if [ $? -gt 0 ]; then
      stat_fail
    else
      rm_daemon ypserv
      stat_done
    fi
    ;;
  restart)
    $0 stop
    sleep 1
    $0 start
    ;;
  *)
    echo "usage: $0 {start
systemd service file
[Unit]
Description=NIS/YP (Network Information Service) Server
Requires=rpcbind.service
After=network.target rpcbind.service

[Service]
Type=forking
PIDFile=/run/ypserv.pid
ExecStart=/usr/sbin/ypserv

[Install]
WantedBy=multi-user.target
ノート: ExecStart や ExecStop などのキーの値はシェル内で実行されず、execv に渡されるだけであることを覚えておいてください。

tmpfiles.d

  • サービスが開始されたときに必要な実行時ディレクトリやファイルを (いくつかの rc スクリプトが行うように) 作成する代わりに、tmpfiles.d(5) 設定ファイルを /usr/lib/tmpfiles.d に含めるようにしてください。
  • systemd に含まれている pacman フックは systemd-tmpfiles --create foo.conf をインストール時に実行して、必要な実行時ファイルが次の起動時ではなくすぐに確実に作成されるようにします。
ヒント: この機能はたくさんの他のことにも使うことができ、例えば必要なファイルの書き込みを、/sys にさえ行うことができます。

modules-load.d

  • サービスが開始されたときに必要なモジュールを (いくつかの rc スクリプトが行うように) 読み込む代わりに、modules-load.d(5) 設定ファイルを /usr/lib/modules-load.d に含めるようにしてください。
  • modprobe 行を post_install (と必要であれば post_upgrade) に追加して、必要なモジュールが次の起動時ではなくインストール時に確実に読み込まれるようにします。

sysctl.d

  • 意見(dreisner): これは一般的に避けられるべきです。低レベルのカーネルの動作をパッケージと結びつけることは悪だと考えられているためです。