SysVinitおぢさんなので。
コレのメモ書き http://www.slideshare.net/enakai/linux-27872553
- SysVinit / UpStart
- systemd の起動処理/操作方法
- journald のログ管理
- Unit設定の書き方
- Tips
SysVinit / Upstart
BIOS が Grub を読み込んで実行 → Grub が Kernel と初期ラムをメモリに展開して Kernel 実行 → Kernel が init Script を実行
-
SysVinit/Upstart は /etc/inittabを元に処理を実行。
-
rc.sysinit (システム初期化
-
rc (サービス起動)
- /etc/init.d/(servise) start
-
migetty/prefdm ログイン受付
-
UpStart
-
RHEL6 にあった
-
実際にジョブとして実行される内容はRHEL5と同じ
-
/etc/init.d/(service) のスクリプトはただのシェルスクリプト
-
Systemd が目指したもの
-
システム起動時間の短縮: 並列実行ではなかったので、遅かった
-
システム構成の動的変更: システム構成の変更に応じて、動的に必要なサービスの起動・停止をしたい
-
プロセス停止処理を標準機能化: 今まではシェルスクリプトで各自実装だったのを、systemd 自身が面倒を見る形
-
デーモン実行環境の制御: サービスごとに関連するプロセスの実行環境(Cgroups によるリソース割当とかアクセス可能なディレクトリなど)を設定するようにしたい。あとログ管理も。
Systemd
- Unit
- SysVinit のスクリプトに含まれていた個々の処理を抜き出し、それらを「Unit」として定義
- 例: rsyslog.service, systemd-remount-fs.service, tmp.mount, proc-sys-fs-binfmt_misc.mount, ..
- Unit のタイプ
- .service: サービス。対応するデーモンが起動
- .target: 何もしない。依存関係や順序関係を定義する時に、複数のUnitをグループ化するのに使用する
- .mount: 有効化するとデバイスなどのマウントをする
- .swap : Swap領域の有効化
- .device: デバイス。udevがデバイスを認識すると有効化
- .socket: systemd が特定のソケットをListenし、接続があると、指定のデーモンを起動してソケットを受け渡す。(xinetd みたいな機能)
- Unitには明示的に設定するのと、自動的に作成するのがある
- .service, .target は設定ファイルで明示的に定義する
- .mount, .swap は /etc/fstab から自動作成
- .device は udev によって自動作成
Unit 定義ファイルの場所
- 二箇所ある。
- /usr/lib/systemd/system/ : システムデフォルト
- /etc/systemd/system/ : 管理者がカスタマイズする場所
- 同じ名前の設定ファイルがある場合、
/etc/systemd/system/
が優先 - システムデフォルトの設定を変更する場合、
/usr/lib/systemd/system/
から/etc/systemd/system
に設定ファイルをコピーして編集 - Unit名がそのまま設定ファイル名になる
- シンボリックリンクでUnitの別名を設定することができる
- ディレクトリ「(Unit名).wants」は依存関係の定義に使用
Unit の依存と順序
- 依存関係: 「A Unit を有効化するなら、B Unit も有効化するべき」
- 順序関係: 「A Unit を有効化する前に、B Unit を有効化するべき」
- systemd が起動すると「default.target」が有効化され、それに依存するUnitがまとめて有効化
- default.target の実態は「multi-user.target」「graphical.target」などへのシンボリックリンク。リンク先をカエルことが「デフォルト runlevelの変更」に相当
~~ 図解 ~~
要は、 default.target のリンクがrescue.target
に向いてる時はrunlevel1
相当になり、multi-user.target
の時はrunlevel3
、graphical.target
の時はrunlevel5
になる。
それぞれ、最低でも local-fs.target
,swap.target
,sysinit.target
, basic.target
が動く。
依存
- syetemd が起動すると、Unitの「依存関係」を元に、有効化されるUnit群を決める
- ただし、起動する「順序関係」は別に定義
- systemd は順序関係を持たないUnitに関しては、出来る限り並列実行を実施する。
- 依存関係の設定。いずれかの方法でやる
- Unit設定ファイルの
[Unit]
セクションで「Wants=」オプション、もしくは「Requires=」オプションで一緒に有効化するUnitを指定 - ディレクトリ「(Unit).wants」「(Unit).requires」内に一緒に有効化するUnitの設定ファイルへのシンボリックリンクをはる
-
Requires
は前提Unitが起動にこけると、このUnitの起動をやめる。Wants
は前提Unitが起動にこけても、このUnitの起動処理を行う - 他に
Conflict=
オプションで、同時に有効化してはいけないUnitの指定ができる
順序
- 順序の設定は次の方法
- Unit 設定ファイルの
[Unit]
セクションにおいて、After=
オプションとBefore=
オプションで指定する -
After=A B C
: 自分自身は、Unit「A」「B」「C」の後に起動する -
Before=A B C
: 自分自身は、Unit「A」「B」「C」の前に起動する
- Unit起動の「待ち合わせ」ポイントとして、target タイプのUnitを利用する
例えば
ネットワーク環境を準備するUnitには「Before=network.target」
ネットワーク環境を使用するUnitには「After=network.target」
-
ネットワークを準備する例
/usr/lib/systemd/system/firewalld.service
Unit
Description=firewalld - dynamic firewall daemon
Before=network.target
Before=libvirtd.target
Before=NetworkManager.service
- ネットワークを利用する例
```/usr/lib/systemd/system/httpd.service
[Unit]
Description=The Apache HTTP Service
After=network.target remote-fs.target nss-lookup.target
このように、network.target
にかます事で、ネットワーク準備と使用のUnit依存をまとめる
- 現在有功なUnit依存、順序はコマンドで確認できる
# systemctl list-dependencies <Unit>
- 指定Unitが必要とするUnitを表示。省略時は「default.target」
- 依存UnitがTargetタイプの時は、さらに、それが必要なUnitを再帰表示
- --all オプションをつけると全てのUnitを再帰表示
# systemctl list-dependencies <Unit> --after
- 指定Unitより先に起動するUnitを表示
- --all オプション有り
# systemctl list-dependencies <Unit> --before
- 指定Unitより後に起動するUnitを表示
- --all オプション有り
動的生成Unit
/usr/lib/systemd/system-generators/ 以下は、システム環境に応じて、動的なUnit生成や、既存Unitの設定変更をする
例:
-
systemd-cryptsetup-generator
-
/etc/crypttab を参照して systemd-cryptsetup@.service を生成
-
systemd-fstab-generator:
-
/etc/fstab を参照して、 mountとswapのUnitを生成
-
mount はマウントポンとのパスで、「/」を「-」に置換したものがUnit名になる
-
systemd-rc-local-generator
-
/etc/rc.d/rc.local が実行可能ファイルの場合、rc-local.service の自動機能を有効化
-
動的に生成されたUnitの設定ファイルは
/run/systemd/generator/
以下に配置される
一覧表示
-
# systemctl list-unit-files
: 従来のchkconfig --list
相当 -
enable:
WantedBy=
指定あり。自動起動が有功 -
disable:
WantedBy=
指定あり。自動起動が無効 -
static:
WantedBy=
指定なし -
# systemctl list-utils
-
現在有功なUnit一覧とその状態を表示
-
--type オプションで特定タイプのUnitのみを表示
-
--type=service で service タイプのみなど。
基本操作
-
# systemctl enable/disable (unit)
-
Unit の自動起動を有効化/無効化する
-
実際には
WantedBy=
で指定されたUnitへの依存関係を設定/削除する -
# systemctl start/stop/restart (unit)
-
Unit をその場で 起動/停止/再起動する
-
reload は、Unit設定ファイルでreloadの動作が定義されている場合のみ使用できる
-
# systemctl status (unit)
-
Unit の実行状態を表示
-
PID や Status や CGroup や関連するデーモンプロセスや直近ログの表示とか
-
# systemctl daemon-reload
-
Unit設定ファイルを変更した時に、変更内容をsystemdに認識させる
-
chkconfig/service のコマンドは、対応するsystemctlコマンドに変換されます
-
サービス起動スクリプトで標準外オプションを使用していたのは、systemdでは使用できなくなる
-
例:
# service postgresql initdb
→# postgresql-setup initdb
CGroup の確認
(そもそもCgroupって何の略だろ…。Categoryかしら)
-
systemd は Cgroup を利用してUnitごとに関連するプロセスを分類
-
# systemd-cgls
: Cgroupによる分類を表示 -
# systemd-cgtop
: リソース利用状況を表示。topコマンドみたいなもの -
Cgroup が同じプロセスに、まとめてシグナルを送信することができる
-
# systemctl kill -s9 sshd.service
-
sshd.service のグループに属するプロセスにKILLシグナルを送る
-
これにより、サービスに関連するプロセス全てを停止させることができる
-
--kill-who=main
オプションをつけると、グループで最初に起動したプロセスのみにシグナルを送る -
systemctl stop
で停止する時にも利用される
- 定義ファイルの
ExecStop=
で指定されたコマンドを実行 - 該当Unitのグループにプロセスが残ってる場合は、まとめて SIGTERMを。
- それでも残ってる場合は SIGKILL
Journald
-
rsyslogd へ出力する内容を、
systemd-journald.service
:通称「journald」に送る -
Journald はメタ情報を追加して、
/var/log/journal/
以下に記録 -
journaldのログはバイナリなので、journalctlコマンドを利用して、検索・表示する
-
systemd では rsyslogd の設定変更が必要
-
従来: Process → /dev/log → rsyslogd
-
systemd: Process → /dev/log → systemd → /run/systemd/journal/syslog → rsyslog
-
rsyslogd には、journaldから直接ログ情報を取得するモジュール
imjournal
があり、UnixSocket/run/systemd/journal/syslog
の代わりに、これを利用するのも可 -
RHEL7ではデフォルトで imjournalが使用
-
imjournal: http://www.rsyslog.com/doc/imjournal.html
Journald の検索
- journalctl
- -u (Unit): 指定ユニットに関係するログのみ表示
- -b: 直前のサーバ起動以降のログを表示
- -f: tail -f のように、順次表示する
- --no-pager: less コマンドを使用しない
- -a : 長いメッセージを省略しない
-
--since='YYYY-MM-DD hh:mm:ss'
: 指定日以降のログ表示 -
--until='YYYY-MM-DD hh:mm:ss'
: 指定日までのログ表示
Unit 設定ファイル文法
-
セクションわけがされている
-
[Install]: 「systemctl enable/disable」コマンドに関連する設定
-
[Service]: Service タイプに固有の設定項目を記載
-
オプションに複数項目を記載するときは、スペース区切りか、同じオプションを複数回に分けて記載
-
Unit セクションの主なオプション
-
Description: 説明
-
Documentation: ドキュメントのURI
-
Requires/Wants: 同時に有効化が必要な前提Unit
-
After: これより先に起動するべきUnit
-
Before: 後に起動するべきUnit
-
Install オプション
-
WantedBy
: enable時にこのUnitの.wantsディレクトリにシンボリックリンクをはる -
RequiredBy
: enable時にこのUnitの.requiredディレクトリにシンボリックリンクをはる -
Also
: enable/disable時に、同時に enable/disableするUnit -
例: syslog/network/auditdの環境が揃ってから起動する。multi-user.target の前提として有効化する。
[Unit]
Description=OpenSSH server daemon
After=syslog.target network.target auditd.service
[Service]
EnvironmentFile=/etc/sysconfig/sshd
ExecStartPre=/usr/sbin/sshd-keygen
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
-
Service タイプのオプション
-
ExecStart: サービス起動コマンド
-
ExecReload: サービス再起動コマンド?
-
ExecStop: サービス停止コマンド
-
ExecStartPre/ExecStartPost: サービス起動前後の追加コマンド/サービス起動判定には関連させたくないコマンドを記載
-
ExecStopPost: サービス停止後に実行するコマンド。サービスが以上停止した際にも実行される
-
EnvironmentFile: 環境変数を読み込むファイル
-
KillMode: ExecStopで停止せずに残ったプロセスの処理方法
-
Type: サービスプロセスの起動完了の判定方法
-
PIDFile: fork型サービスのメインプロセスのPIDファイル
-
BusName: D-Bus型サービスのbus接続名
-
Restart: サービスプロセス停止時の再起動条件(Default: no)
-
User/Group : プロセスを起動するユーザ/group
-
PrivateTmp: このサービス専用の/tmpと/var/tmpを用意する
-
ReadOnlyDirectories: 指定のディレクトリ以下をReadOnlyモードにする
-
InaccessibleDirectories: 指定ディレクトリ以下をアクセス不可にする
-
RootDirectory: 指定ディレクトリにchrootする
-
これらの機能は、ファイルシステムのネームスペースを分離することで実現している。そのため、サービスを提供するプロセスがこのネームスペース内で実施したバインドマウントは、他のプロセスからは見えなくなるという制限がある。(chroot した時に /dev/urandom ねーぞとか。)
-
Typeはサービスの起動完了を判定するタイミングを指定
-
Type=simple
: 指定コマンドがフォアグラウンドで実行を継続する場合。コマンドを実行したらすぐに起動完了と判定 -
Type=forking
: 子プロセスをバックグラウンドで起動して、最初のコマンドをは終了する場合。最初のコマンドが終了したタイミングを起動完了と判断 -
Type=oneshot
: 一度だけコマンドを実行するタイプのサービスの場合。コマンドが終了したら起動完了と判定して、サービスも終了したものと認識。(RemainAfterExit=yes
を指定すると、コマンド終了後もサービスは起動したままと認識。) -
Type=notify
: systemdのライブラリ関数「sd_notify()」を使用する場合。プロセスのプログラム内部で、sd_notify()関数で起動完了を通知するように作られている必要が有ります。 -
Type=dbus
: D-Bus(プロセス間通信用メッセージバス)を利用するサービスの場合。BusNameで指定した接続名がD-BUsに登録されると、サービス起動完了と判定
プロセスが異常終了したときの動作設定
-
restartオプションでサービスの再起動を行うか指定
-
Restart=no: サービスの再起動は行いません
-
Restart=always: サービスの再起動を行う
-
デフォルトでは10秒の間に5回以上再起動すると、次の10秒間は再起動を試みない。一般では「
StartLimitInterval
の間にStartLimitBurst
回以上再起動すると、次のStartLimitInterval
の間は再起動を試みない」 -
systemdは起動したサービスに関連する全てのプロセスをCgroupの個別のグループに入れて管理している
-
ExecStopコマンドで停止した時、グループ内にプロセスが残っている場合、KillModeの設定に応じて残プロセス処理を行う
-
KillMode=none
残プロセスは放置 -
KillMode=process
メインプロセスが残っている場合、SIGTERM/SIGKILLで停止する。その他の残プロセスは放置 -
KillMode=control-group
グループ内の全ての残プロセスを SIGTERM/SIGKILL で停止する -
KillMode=mixed
メインプロセスを SIGTERM/SIGKILL で停止し、続けてグループ内の全ての残プロセスを SIGKILL で停止する。
Type=forking?
Type=forking はメインプロセスの追跡にPIDファイルが必要になることから、systemdのサービス設定ではType=Forking
よりType=simple
,Type=notify
の利用が推奨される。
- Apache httpd では mod_systemdモジュールで systemd に対応している
Tips
Unitの無効化
# systemctl mask/unmask (Unit)
- 指定のUnit を無効化/有効化する。
mask
を使用した場合、disable
と異なりsystemctl start
で手動起動もできなくなります。 - mask による無効化は、
/etc/systemd/system
以下に /dev/null へのシンボリックリンクをはることで行われる。/etc/systemd/system
以下に設定ファイルを作成している場合は、maskによる無効化はできない
テンプレートタイプの設定ファイル
- hoge@.service は 「hoge@<任意の文字列>.service」という複数サービスの設定ファイルとして機能する
-
# systemctl start hoge@huga.service
: 「hoge@huga.service」にしたがってサービス「hoge@huga.service」が起動する。この際、設定ファイルの「%I」が「<任意の文字列>」(この場合huga
)に置換される(「%i」は「%I」内の記号文字を独自ルールでエスケープしたものになる) -
# systemctl enable hoge@huga.service
: .wantsディレクトリ内に、「hoge@huga.service」から「hoge@.service」へシンボリックリンクがはられます。これにより、「hoge@huga.service」を自動起動しようとしますが、実際には「hoge@.service」の設定が使用される