LFCS — Linux Foundation認定システム管理者
ユニットファイルとスケジューリング設定を書く
目標
systemdのユニットファイルとタイマー、cronファイル、ログローテーションの設定、ドロップインのオーバーライドを、文法とセクションの規則を守って自分で書きます。
なぜ重要なのか
このラボ環境はsystemctlが塞がれていて、サービスを起動できません。そのため、採点はすべてファイルの内容で行います。一見、損のように見えますが、実際には、試験で最も間違える箇所に、ちょうど集中できるようになります。LFCSでユニットの問題を落とす理由は、サービスが起動しないからではなく、ディレクティブを間違ったセクションに入れたり、形式を間違えたりするからです。WantedByを[Service]に書くと有効化できず、タイマーのWantedByはmulti-user.targetではなくtimers.targetで、/etc/cron.dのファイルにはユーザーフィールドがもう1つ入ります。ドロップインでExecStartを変更するときに、空行で一度空にしないと、コマンドが2つになって起動に失敗します。すべて、ファイルを見るだけで見つけられるエラーです。
ステップ
/root/lfcs-svc/lfcs-api.serviceを作成し、[Unit]、[Service]、[Install]の3つのセクションを、この順序で置いてください。[Unit]には、値が空でないDescription=を入れてください。- 同じファイルに、
After=network-online.target、Wants=network-online.target、Type=simple、ExecStart=/usr/local/bin/lfcs-api --port 8080、Restart=on-failure、RestartSec=5、User=lfcsapi、WantedBy=multi-user.targetを、それぞれ適切なセクションに入れてください。 /root/lfcs-svc/lfcs-backup.timerに、[Timer]セクションと、OnCalendar=*-*-* 03:30:00、Persistent=true、Unit=lfcs-backup.serviceを入れ、WantedBy=timers.targetで有効化してください。対になる/root/lfcs-svc/lfcs-backup.serviceには、Type=oneshotとExecStart=/usr/local/bin/lfcs-backup.shを入れてください。/etc/cron.d/lfcs-reportを作成し、*/15 * * * * root /usr/local/bin/lfcs-report.shで始まる行を入れてください。ただし、出力は/var/log/lfcs-report.logへ送ってください。/root/lfcs-svc/lfcsops.crontabに、ユーザーcrontab形式で30 2 * * 1-5 /usr/local/bin/lfcs-rotate.shを入れてください。この形式には、ユーザーフィールドがありません。/etc/cron.d/lfcs-reportで、スケジュールの行よりも前に、SHELL=/bin/bashとPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binの2行を入れてください。/root/lfcs-svc/lfcs-report.logrotateに、/var/log/lfcs-report.logのブロックを作成し、daily、rotate 14、compress、delaycompress、missingok、notifempty、create 0640 root admを入れてください。/root/lfcs-svc/lfcs-api.service.d/override.confを作成して、[Service]の下に、値が空のExecStart=を先に置き、続けてExecStart=/usr/local/bin/lfcs-api --port 9090とMemoryMax=512Mを入れてください。
参考
- この環境では、
systemctlが動作しません。採点はファイルの内容だけで行います。実際のサーバーなら、systemd-analyze verifyで文法を見て、systemctl daemon-reloadで反映します。 StartLimitIntervalSecとStartLimitBurstは、[Service]ではなく[Unit]セクションのディレクティブです。ExecStart=では、パイプとリダイレクトが効きません。systemdがシェルを経由せずに実行するからです。- よくある間違い:
/etc/cron.dの下のファイル名にドットが入っていると、無視されます。拡張子を付けないでください。
ユニットファイルの骨格を作る
/root/lfcs-svc/lfcs-api.serviceを作成し、[Unit]、[Service]、[Install]の3つのセクションを、この順序で置いてください。[Unit]には、値が空でないDescription=を入れてください。
ユニットファイルはINI形式で、セクション名は角括弧で囲みます。3つのセクションの順序と大文字・小文字を、正確に合わせてください。
実行・再起動・有効化のディレクティブ
同じファイルに、After=network-online.target、Wants=network-online.target、Type=simple、ExecStart=/usr/local/bin/lfcs-api --port 8080、Restart=on-failure、RestartSec=5、User=lfcsapi、WantedBy=multi-user.targetを、それぞれ適切なセクションに入れてください。
各ディレクティブは、どのセクションに属するかが決まっています。有効化の対象は[Install]に、実行方式は[Service]に、順序の依存は[Unit]に入ります。
タイマーユニットと対のサービス
/root/lfcs-svc/lfcs-backup.timerに、[Timer]セクションと、OnCalendar=*-*-* 03:30:00、Persistent=true、Unit=lfcs-backup.serviceを入れ、WantedBy=timers.targetで有効化してください。対になる/root/lfcs-svc/lfcs-backup.serviceには、Type=oneshotとExecStart=/usr/local/bin/lfcs-backup.shを入れてください。
タイマーは自分では仕事をせず、同じ名前のユニットを起こします。停止している間に過ぎた実行に追いつかせるディレクティブが、別にあります。
/etc/cron.dファイルの作成
/etc/cron.d/lfcs-reportを作成し、*/15 * * * * root /usr/local/bin/lfcs-report.shで始まる行を入れてください。ただし、出力は/var/log/lfcs-report.logへ送ってください。
システムのcronファイルは、時刻の5つのフィールドの後ろに、実行ユーザーのフィールドがもう1つ入ります。出力を残さないと、cronがメールで送ろうとします。
ユーザーcrontabの形式
/root/lfcs-svc/lfcsops.crontabに、ユーザーcrontab形式で30 2 * * 1-5 /usr/local/bin/lfcs-rotate.shを入れてください。この形式には、ユーザーフィールドがありません。
ユーザーcrontabには、ユーザーフィールドがありません。曜日のフィールドでは、範囲はハイフンで書きます。
cronのPATHの問題
/etc/cron.d/lfcs-reportで、スケジュールの行よりも前に、SHELL=/bin/bashとPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binの2行を入れてください。
環境変数の行は、スケジュールの行よりも前にあって初めて適用されます。cronがデフォルトで渡すPATHは、ログインシェルのものよりずっと短いという点が、このステップの理由です。
ログローテーションの設定
/root/lfcs-svc/lfcs-report.logrotateに、/var/log/lfcs-report.logのブロックを作成し、daily、rotate 14、compress、delaycompress、missingok、notifempty、create 0640 root admを入れてください。
対象のパスの後ろに波括弧のブロックを開いて、ディレクティブを1行ずつ入れます。ローテーション直後に作成する新しいファイルの権限と所有権を指定するディレクティブがあります。
ドロップインのオーバーライド
/root/lfcs-svc/lfcs-api.service.d/override.confを作成して、[Service]の下に、値が空のExecStart=を先に置き、続けてExecStart=/usr/local/bin/lfcs-api --port 9090とMemoryMax=512Mを入れてください。
ドロップインのディレクトリ名は、ユニットファイル名に接尾辞が付いた形です。リスト型のディレクティブは、値を空にした行を先に置かないと、既存の値に追加されます。