Linux環境におけるシステム管理では、バックアップ、ログローテーション、定期的なメンテナンスなどを自動化することが運用負荷の軽減と信頼性向上に不可欠です。この自動化を実現する仕組みが「ジョブスケジューリング」です。
Linuxには主に以下の3つのスケジューリング機能が標準で用意されています。
at: 指定した未来の特定の時刻に、一度だけタスクを実行します。cron: 定義されたタイムテーブルに従い、タスクを定期的に繰り返し実行します。anacron: システム停止により missed された定期タスクを、次回起動時に補完実行するシステムレベルの拡張機能です。
単発ジョブのスケジューリング:at
未来の特定のタイミングで一度だけ処理を実行したい場合、atコマンドを使用します。この機能を利用するには、バックグラウンドでatdデーモンが稼働している必要があります。モダンなLinuxディストリビューションでは以下のようにサービス状態を確認・制御します。
systemctl status atd
# 稼働していない場合は起動し、自動起動を有効化します
sudo systemctl start atd
sudo systemctl enable atd
タスクの登録と管理
atコマンドの後に実行したいタイミングを指定し、プロンプトから実行するコマンドを入力します。入力の完了はCtrl+Dで行います。
# 5分後にバックアップスクリプトを実行する
$ at now + 5 minutes
at> /usr/local/bin/db_backup.sh > /var/log/backup.log 2>&1
at> <EOT>
job 14 at Fri Oct 27 10:30:00 2023
# 特定の年月日と時間を指定して実行
$ at 14:00 Dec 25
at> /opt/scripts/send_greetings.sh
at> <EOT>
job 15 at Mon Dec 25 14:00:00 2023
登録された待機中のタスクはatqコマンドで確認でき、不要になったタスクはatrm [ジョブID]で削除できます。
$ atrm 14
$ atq
内部的には、スケジュールされたタスクはテキストファイルとして/var/spool/at/ディレクトリ内に保存され、atdデーモンによってポーリング・実行されます。権限を持つユーザーであれば、このディレクトリから直接ファイルを削除してタスクをキャンセルすることも可能です。
定期ジョブの自動化:cron
cronは、設定されたスケジュールに基づいてコマンドを自動実行する強力なツールです。バックグラウンドではcrondデーモンが動作しています。ユーザー固有のスケジュールはcrontabコマンドを通じて管理され、設定ファイルは/var/spool/cron/配下に保存されます。
crontab -e # 現在のユーザーのcronテーブルをエディタで開く
crontab -l # 登録済みのcronジョブを一覧表示する
crontab -r # 現在のユーザーのcronテーブルを完全に削除する
crontab -u username -e # 特定ユーザーのcronテーブルを操作する(要root権限)
crontabの構文
crontab -eでエディタが起動すると、以下のようなフォーマットで時間とコマンドを定義します。
# ┌───────────── 分 (0 - 59)
# │ ┌───────────── 時 (0 - 23)
# │ │ ┌───────────── 日 (1 - 31)
# │ │ │ ┌───────────── 月 (1 - 12)
# │ │ │ │ ┌───────────── 曜日 (0 - 6) (日曜日は0または7)
# │ │ │ │ │
# * * * * * command_to_execute
各フィールドでは、特殊文字を使用して柔軟なスケジューリングが可能です。
*: すべての値(例:「分」に指定すれば毎分),: 値のリスト(例:1,15なら1と15)-: 値の範囲(例:1-5なら1から5まで)/: ステップ値(例:*/2なら2単位ごと)
実践的なcrontabの設定例
実際の運用でよく使用されるスケジューリングの例を以下に示します。
# 1. 毎日深夜2時15分にNginxをリロードする
15 2 * * * /usr/sbin/nginx -s reload
# 2. 毎月1日、10日、22日の午前4時45分にデータベースの最適化を実行
45 4 1,10,22 * * /usr/bin/mysqlcheck --optimize --all-databases
# 3. 毎週末(土曜と日曜)の午前1時10分に古いログをアーカイブする
10 1 * * 6,0 /opt/scripts/archive_logs.sh
# 4. 平日の午後6時から午後11時の間、30分ごとにAPIサーバーのヘルスチェックを行う
0,30 18-23 * * 1-5 /usr/bin/curl -s http://localhost:8080/health > /dev/null
# 5. 1時間ごとにキャッシュディレクトリの一時ファイルをクリーンアップする
0 * * * * /usr/bin/find /var/cache/app -type f -mmin +60 -delete
# 6. 12月中の毎日、午前6時から午後12時の間で3時間ごとにシステムメトリクスを収集
0 6-12/3 * 12 * /usr/local/bin/collect_metrics.sh
# 7. 毎日午前0時20分、2時20分、4時20分...と2時間ごとにカスタム監視アラートを実行
20 0-23/2 * * * /usr/bin/logger "Routine monitoring alert executed"
複雑な設定は、あらかじめ記述したテキストファイルを用意し、crontab filenameコマンドを用いて一括でインポートすることも推奨されます。
システム全体のスケジューリングとanacron
ユーザー単位のcrontab -eとは別に、システム全体のジョブを管理するための/etc/crontabが存在します。このファイルには、実行ユーザーを指定するためのフィールドが追加されています。
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=admin@example.com
# 1時間ごとに /etc/cron.hourly 内のスクリプトをroot権限で実行
01 * * * * root run-parts /etc/cron.hourly
run-partsは、指定されたディレクトリ内のすべての実行可能スクリプトを順次実行するユーティリティです。/etc/cron.daily、/etc/cron.weeklyなどのディレクトリにスクリプトを配置するだけで、システム標準の定期タスクに組み込むことができます。
anacronによる実行漏れの防止
cronはシステムが24時間稼働していることを前提としています。ラップトップや定期的にシャットダウンされるサーバーでは、電源がオフになっている間に実行されるはずだったタスクが missed(未実行)になる問題があります。
これを解決するのがanacronです。anacronは、前回の実行からの経過時間をチェックし、指定された間隔内に実行されていなかったタスクを、システム起動後の遅延時間経過後に補完実行します。設定ファイルは/etc/anacrontabです。
# 書式: period delay job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
- period: タスクを実行する頻度(日数)。
@monthlyのようなマクロも使用可能。 - delay: システム起動後、タスクを実行するまでの遅延時間(分)。
- job-identifier: ジョブの識別子。タイムスタンプファイル(
/var/spool/anacron/配下)の名前として使用され、重複実行を防ぐ。 - command: 実行するコマンドまたはスクリプト。