systemdをいじったときのメモ

はじめに

How to boot up Fedora 15 with systemd inside Libvirt LXC · GitHubを書いたときに知ったsystemdについてのメモです。

systemdが起動していないときにファイルをいじる方法が主で、systemctlコマンドの使い方についてはあまり書かれていません。あしからず。

Systemdのバージョンは26(Fedora 15のもの)です。

systemdとは?

  • sysvinitやUpstartの仲間
  • Upstartと同じくsysvinit互換のrcスクリプトが使える
  • sysvinit/Upstartとの比較はここの表がわかりやすい
  • D-BUSとかPOSIX CapabilitiesとかcgroupsとかPlymouthとかInotifyとかPolicyKitとかいろいろな機能をバリバリ使ってる
    • 移植性?そんなの関係ねー!
  • いろいろな起動タスクや資源を定義して、それらの依存関係を記述することでブート順序を制御できる
  • 既存関係をみて可能ならば並行実行する
  • などなど

コマンドやファイル

  • /sbin/systemctl: 起動タスクの制御、状態の表示、依存関係のグラフ化などいろんなことができるコマンド
    • これ一つだけで大体できる
    • sysvinit互換のservice/chkconfigコマンドもある
  • /etc/systemd/system.conf: systemd自身の設定ファイル
  • /lib/systemd/system/: 起動タスクの定義ファイルがある場所
  • /etc/systemd/system/: システムローカルの起動タスクの定義ファイルがある場所
    • 起動タスクの挙動を変えたい時はこっちをいじる
  • /etc/systemd/system/default.target: sysvinitでいうところのrunlevelの設定。/lib/systemd/system/のファイルへのシンボリックリンク
    • デフォルトは/lib/systemd/system/graphical.target (runlevel=5)
    • runlevel=3にしたければ、ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
  • man systemd: マニュアル
    • 他にもsystemd.*ってマニュアルがいっぱいあるので一通り目を通しておくと良い

起動タスク/資源の定義ファイル

起動タスクや資源にはいろいろ種類があるけど、ひっくるめてunitと呼んでいる。

  • service: コマンドを実行したり、デーモンを起動したりする
  • target: 自身では何も実行しない。unitのグループ化などに用いられる
  • mount, automount: マウントポイントを表わす定義ファイル。automountには対応するmountが必要
    • mountには何をどこにマウントするかを記述する。automountに記述するか、依存関係の結果によりブート時に自動的にマウントされる
    • automountはその名の通りブート時にマウントさせたいときに使う。依存関係にないが、自動的にマウントさせたいときに使う(たぶん)
  • socket: UNIXドメインソケットやFIFOIPアドレス&ポート番号などのIPC/通信資源を表わす
    • 接続要求があったら対応するserviceを起動する
    • serviceを永続的に起動しておく場合(D-BUSやsyslogデーモン)と、接続要求ごとに起動する場合(xinetdのようなもの)がある
  • path: ファイルやディレクトリ資源を監視して、状態に合わせてserviceを起動/有効化する
    • 指定ファイルに変化があったらserviceを起動するとか、指定ディレクトリが空でない場合(≒ファイルが存在する限り)対応するserviceを起動しておくとか

依存関係などの記述方法

Unitによって記述できる内容は違う。詳しくはman systemd.*参照(例えば、systemd.targetやsystemd.service)

サンプルとしてfedora-autorelabel.serviceを載せる。

[Unit]
Description=Relabel all filesystems, if necessary
DefaultDependencies=no
Requires=local-fs.target
Conflicts=shutdown.target
After=local-fs.target
Before=sysinit.target shutdown.target
ConditionSecurity=selinux
ConditionKernelCommandLine=|autorelabel
ConditionPathExists=|/.autorelabel

[Service]
ExecStart=/lib/systemd/fedora-autorelabel
Type=oneshot
TimeoutSec=0
RemainAfterExit=yes
StandardInput=tty
  • Requires: 当該unitが動いているときは指定したunitも起動しなければならない(動いていなければならない)
    • 順序関係はない。つまり、並行起動可能である(ただし、後述のBefore/Afterが指定されていない場合)
    • 後に起動したunitが何らかの理由で起動しなかった場合には、当該unitも起動しない(すでに起動していた場合は終了する)
  • Conflicts: 当該unitが動いているときは指定したunitは起動してはならない(動いていてはならない)
    • 使い方の一つは終了処理。shutdown.targetを入れておいて、シャットダウン時にshutdown.targetを強制起動させると、依存関係により当該unitを停止させようとする=終了処理が実行される
  • Wants: 当該unitが起動さえるとき、指定したunitの起動も試みる
  • Before: 当該unitは指定unitが起動する前に起動しなければならない
  • After: 当該unitは指定unitが起動した後に起動しなければならない
  • Condition*: 指定した条件を満たした場合のみ起動する

詳しくはman systemd.unitを参照。

知っておくと良いかもしれないこと

  • unitを無効にしたい場合は/etc/systemd/systemディレクトリ内に当該定義ファイル名の/dev/nullへのシンボリックリンクを作れば良い
    • 例: ln -sf /dev/null /etc/systemd/system/sysinit.service
    • 無効にすると当該unitをRequiresしているunitは当該unitを無視して起動する
    • もちろん、その結果、依存する処理が実行されず起動に失敗するかもしれないので取り扱いには注意
  • systemdは定義ファイルにないmountを行なう
    • /sysや/runなど
  • systemdは暗黙的に依存関係を追加している
    • basic.targetはsysvサービスをRequires/Afterしている
    • 詳しくはman systemd.special参照
  • socket unitを遅延起動するためにsystemdは当該資源をepollで監視してる
    • 当該資源にデータが届いたら、オンデマンドに当該serviceを起動する
  • 起動するgettyを減らしたい時は/etc/systemd/system/getty.target.wants/以下のシンボリックリンクを削除すれば良い
  • systemctl dotで依存関係のグラフ(Grapvizのdotコマンドで扱える形式)を生成することができる
  • 依存関係はsystemctl show -p Requires basic.targetなどで調べることができるけど、systemctl dot |grep basic.targetの方がわかりやすい場合がある