サーバーの価値は、あなたが寝ている間に働くことにあります。バックアップ、ログのローテーション、証明書の更新、9時のレポート。Linuxにはそのためのスケジューラーが2つあります。cronは40年の歴史があり、1行で済みます。systemdタイマーは小さなファイルが2つ必要ですが、その代わりにログ、停止後の補完、正確な時刻が手に入ります。このガイドではUbuntu 24.04で両方を扱い、すべての挙動を当社イメージの新しいサーバーで確認しました。cronのジョブが何も言わずに失敗する3つのミスも含みます。
sudoを使えるユーザーが必要です。Ubuntuのセットアップガイドで作成できます。
1. 5分でわかるcron
cronは当社のUbuntuとDebianのイメージにインストール済みで、動いています。ユーザーごとにジョブの表があり、自分の表はこれで編集します。
crontab -e
各行は5つの時刻フィールドとコマンドです。
# min hour day month weekday command
30 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * /usr/local/bin/check.sh
0 9 * * 1-5 /usr/local/bin/report.sh
@reboot /usr/local/bin/start-tunnel.sh
つまり、毎晩03:30、5分ごと、平日の09:00、そして起動のたびに1回です。*/5は5つごと、1-5は範囲、1,15はリストです。サーバーのタイムゾーンが使われ、当社のイメージではUTCです。ホスト名とタイムゾーンのガイドで一度設定すれば、cronはそれに従います。
何が実行されたかはjournalctl -u cronで確認します。実行ごとにユーザーとコマンドが記録され、3つの落とし穴もそこに現れます。
落とし穴1:出力が消える。 cronはジョブの出力をユーザーにメールします。当社のイメージにはメールサーバーがないため、journalに(CRON) info (No MTA installed, discarding output)と記録され、出力は失われました。最初の例のように>> /var/log/backup.log 2>&1で自分でリダイレクトしてください。
落とし穴2:パーセント記号。 crontabでは%がコマンドを終わらせ、残りを標準入力に変えます。date +%F > /tmp/todayをスケジュールしたところ、journalには実際に実行された内容CMD (date +)が残っていました。ファイルは作られず、エラーも届きませんでした。\%と書くか、コマンドをスクリプトにしてそのスクリプトをスケジュールしてください。
落とし穴3:環境の違い。 cronはジョブをbashではなく/bin/shで、ホームディレクトリから、最小限の環境で実行します。Ubuntu 24.04のPATHは評判より良く、rootでも一般ユーザーでも/usr/local/binと/snap/binを含むシステムの完全なパスでした。それでも足りないのはホームディレクトリ以下のすべてで、~/.local/bin、nvmのnode、pipx、cargoです。ジョブではフルパスを使うか、行を. $HOME/.profile;で始めてください。
ユーザーではなくシステムに属するジョブは、ユーザーという項目を1つ加えたファイルとして/etc/cron.d/に置きます。
30 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
Ubuntuは/etc/cron.hourly、cron.daily、cron.weekly、cron.monthlyの中身も実行します。毎時17分、06:25、日曜日の06:47、毎月1日の06:52です。実行可能なスクリプトを置けば、ほかと一緒に実行されます。
2. systemdタイマー
タイマーは2つのユニットでできています。作業をするサービスと、いつ実行するかを決めるタイマーです。まずスクリプトを作り、次にユニットを作ります。
sudo nano /usr/local/bin/backup.sh
sudo chmod +x /usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run the backup every night at 03:30
[Timer]
OnCalendar=*-*-* 03:30
Persistent=true
AccuracySec=1m
[Install]
WantedBy=timers.target
有効にするのはサービスではなくタイマーです。
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer
list-timersは次回の実行、それまでの残り時間、前回の実行を表示します。ログの設定は不要で、journalctl -u backup.serviceに開始、終了、出力の各行がタイムスタンプ付きで残ります。今すぐジョブを実行するにはsudo systemctl start backup.serviceです。スケジュールを信頼する前のスクリプトのテストにも使えます。
カレンダーの書式。 OnCalendarは曜日 年-月-日 時:分:秒と読み、*は任意の値です。使う前に式を確かめましょう。
systemd-analyze calendar "Mon..Fri *-*-* 03:00" --iterations 2
正規化された形と次の日時が表示されます。確認した式の例です。
| OnCalendar | 意味 |
|---|---|
*-*-* 03:30 | 毎日03:30 |
Mon..Fri *-*-* 09:00 | 平日の09:00 |
*:0/15 | 15分ごと |
weekly | 月曜日の00:00 |
*-*-01 04:00 | 毎月1日の04:00 |
*-*-* 03:00 Europe/Kyiv | キーウ時間の03:00。テストでは01:00 UTCに実行 |
知っておきたい3つの設定。 Persistent=trueは前回の実行をディスクに記録し、サーバーの停止中やタイマーの停止中に逃した実行を補完します。2分ごとのタイマーを止め、予定の実行が過ぎるのを待ってから再開したところ、逃した実行は同じ秒のうちに始まりました。Persistentがなければ、次の予定を待つだけです。
驚きはAccuracySecです。systemdはデフォルトで、起こす回数を減らすためにタイマーを1分の幅でまとめるので、最初の実行は07:42:00ではなく07:42:18でした。AccuracySec=1sにすると、その後の実行は07:46:00と07:48:00に秒単位で正確に揃いました。分が重要なときに設定し、夜間バックアップならデフォルトのままで構いません。
RandomizedDelaySec=10mはあえて逆のことをします。開始を一定の幅に散らし、10台のサーバーが同じ秒に同じバックアップ先へ殺到しないようにします。
1回だけのジョブならファイルは不要です。
sudo systemd-run --on-active=30m --unit=cleanup-once /usr/local/bin/cleanup.sh
1回だけ動いて消える一時的なタイマーが作られ、それまではsystemctl list-timersに表示されます。
3. どちらを使うか
| cron | systemdタイマー | |
|---|---|---|
| 設定 | 1行 | ファイル2つ |
| ログ | 出力をリダイレクトした場合のみ | journalctl -u name.service |
| サーバー停止中に逃した実行 | 失われる | Persistent=trueで起動時に実行 |
| 次の時刻にまだジョブが動いている | 2つ目が起動する | 1つ目が終わるまでスキップ |
| 正確な時刻 | 分単位 | AccuracySec=1sで秒単位 |
| ステータス | なし | list-timers、systemctl status |
1年後に見ても分かる簡単な1行ならcronを使います。失敗に気づく必要があるもの、重複してはいけないもの、再起動で逃しても実行すべきものにはタイマーを使います。バックアップ、証明書の更新、データベースのクリーンアップなどです。cronのジョブが重なる可能性があるなら、flock -n /tmp/backup.lock /usr/local/bin/backup.shで包めば、2つ目はすぐに終了します。
どちらのスケジューラーもジョブを起動したら終わりです。常に動き続け、クラッシュ後に復帰すべきプログラムには、スケジュールではなくサービスが必要です。systemdサービスの作り方と、WindowsならWindows Serverでスクリプトを24時間動かす方法を参照してください。最初のタイマーにはresticによるバックアップのガイドのものがおすすめです。自動セキュリティ更新はUbuntuに最初から入っているタイマーapt-daily-upgrade.timerで、新しいサーバーで動く17個のうちの1つです。
コメント
まだコメントはありません。最初になりましょう。