サーバー運用では、バックアップの取得、ログの整理、データベースのメンテナンスなど、定期的に繰り返す作業が数多く存在します。これらを毎回手動で行うのは非効率であり、実行忘れのリスクも伴います。Linuxのcronは、こうした定期タスクを自動化するための標準的な仕組みです。
本記事では、cronの基本概念からcrontabの書き方、実務で使える設定例、よくあるトラブルとその対処法までを体系的に解説します。Linuxの基礎と基本コマンドを理解した方が、タスク自動化の実践スキルを身につけるのに最適な内容です。
cronとは?定期実行の仕組みを理解する
cronは、Linuxにおけるジョブスケジューラです。指定した日時やスケジュールに従って、コマンドやスクリプトを自動的に実行します。cronデーモン(crond)がバックグラウンドで常駐し、毎分スケジュールを確認して実行すべきタスクがあれば起動します。
cronの構成要素
cronの定期実行には、主に以下の要素が関わっています。
| 要素 | 説明 |
|---|---|
| cronデーモン(crond) | バックグラウンドで動作し、スケジュールを監視するサービス |
| crontab | ユーザーごとのスケジュール設定ファイル |
| /etc/crontab | システム全体のスケジュール設定ファイル |
| /etc/cron.d/ | パッケージが配置するスケジュール設定ディレクトリ |
| /etc/cron.daily/ 等 | 日次・週次・月次で自動実行されるスクリプト配置場所 |
cronデーモンの状態確認
cronを使う前に、cronデーモンが動作していることを確認しましょう。
# cronデーモンの状態を確認
$ systemctl status cron # Ubuntu/Debian
$ systemctl status crond # CentOS/Rocky Linux
# 起動していない場合は起動して自動起動も設定
$ sudo systemctl enable --now cron
cronデーモンはsystemdによって管理されています。プロセス管理の知識があれば、cronデーモンの状態確認もスムーズに行えます。
crontabの書式を理解する
crontabの設定は、決められた書式に従って記述します。この書式を正確に理解することが、cron活用の第一歩です。
crontabの基本書式
# ┌───────────── 分(0-59)
# │ ┌───────────── 時(0-23)
# │ │ ┌───────────── 日(1-31)
# │ │ │ ┌───────────── 月(1-12)
# │ │ │ │ ┌───────────── 曜日(0-7、0と7は日曜日)
# │ │ │ │ │
# * * * * * 実行するコマンド
各フィールドで使える特殊文字は以下のとおりです。
| 記号 | 意味 | 例 |
|---|---|---|
| * | すべての値にマッチ | * = 毎分、毎時 など |
| , | 複数の値を指定 | 1,15 = 1と15 |
| - | 範囲を指定 | 1-5 = 1から5まで |
| / | 間隔を指定 | */5 = 5ごと |
スケジュール設定の具体例
# 毎日午前3時に実行
0 3 * * * /path/to/script.sh
# 毎時0分に実行(1時間ごと)
0 * * * * /path/to/script.sh
# 5分ごとに実行
*/5 * * * * /path/to/script.sh
# 毎週月曜日の午前9時に実行
0 9 * * 1 /path/to/script.sh
# 毎月1日と15日の午前2時に実行
0 2 1,15 * * /path/to/script.sh
# 平日(月〜金)の午前8時から午後6時まで30分ごとに実行
*/30 8-18 * * 1-5 /path/to/script.sh
# 毎年1月1日の午前0時に実行
0 0 1 1 * /path/to/script.sh
定義済みスケジュール文字列
多くのcron実装では、よく使うスケジュールを簡潔に記述できる特殊文字列もサポートしています。
| 文字列 | 意味 | 等価な書式 |
|---|---|---|
| @reboot | システム起動時に1回実行 | - |
| @yearly | 年に1回(1月1日 0:00) | 0 0 1 1 * |
| @monthly | 月に1回(1日 0:00) | 0 0 1 * * |
| @weekly | 週に1回(日曜 0:00) | 0 0 * * 0 |
| @daily | 1日1回(0:00) | 0 0 * * * |
| @hourly | 1時間に1回(0分) | 0 * * * * |
# システム起動時にサービスを自動実行
@reboot /opt/app/start.sh
# 毎日実行
@daily /opt/scripts/daily-report.sh
crontabの操作方法
crontabの登録・編集・確認・削除はすべてcrontabコマンドで行います。
基本的なcrontab操作
# 現在のcrontabを表示
$ crontab -l
# crontabを編集
$ crontab -e
# crontabを削除(すべてのジョブを削除)
$ crontab -r
# 削除前に確認プロンプトを表示
$ crontab -ri
# 他のユーザーのcrontabを表示(root権限が必要)
$ sudo crontab -l -u tanaka
# 他のユーザーのcrontabを編集
$ sudo crontab -e -u tanaka
crontab -eを初めて実行すると、使用するエディタの選択を求められる場合があります。エディタの操作に不安がある方は、Vimの基本操作ガイドを先に確認しておくと安心です。
システム全体のcron設定
ユーザーのcrontabとは別に、システム全体の定期タスクを設定する方法もあります。
# /etc/crontab(システム全体の設定)
# ユーザー指定フィールドがある点が通常のcrontabと異なる
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=admin@example.com
# 分 時 日 月 曜日 ユーザー コマンド
0 3 * * * root /opt/scripts/backup.sh
*/10 * * * * www-data /opt/scripts/cache-clear.sh
また、スクリプトを以下のディレクトリに配置するだけで自動実行される仕組みも用意されています。
/etc/cron.hourly/ # 1時間ごとに実行
/etc/cron.daily/ # 1日1回実行
/etc/cron.weekly/ # 1週間に1回実行
/etc/cron.monthly/ # 1ヶ月に1回実行
これらのディレクトリは、Linuxのディレクトリ構造における/etcの管理ファイルの一部です。配置するスクリプトには実行権限が必要で、ファイル名に拡張子(.sh等)を含めないことが推奨されています。
実務で使えるcron設定例
ここでは、サーバー運用で実際によく使われるcronの設定例を紹介します。
データベースの自動バックアップ
# 毎日午前3時にMySQLのバックアップを取得
0 3 * * * /usr/bin/mysqldump -u backup_user -p'PASSWORD' --all-databases | /usr/bin/gzip > /backup/mysql/db_$(date +\%Y\%m\%d).sql.gz 2>> /var/log/backup.log
# 7日以上前のバックアップファイルを自動削除
0 4 * * * /usr/bin/find /backup/mysql/ -name "*.sql.gz" -mtime +7 -delete
重要な注意点:crontab内で%はエスケープが必要です。date +%Y%m%dはcrontab内ではdate +\%Y\%m\%dと記述します。これはcronでよくあるトラブルの一つです。
ログファイルの定期クリーンアップ
# 毎週日曜日の午前2時に古いログファイルを圧縮・削除
0 2 * * 0 /opt/scripts/log-cleanup.sh
log-cleanup.shの内容例:
#!/bin/bash
# 30日以上前のログを圧縮
find /var/log/app/ -name "*.log" -mtime +30 -exec gzip {} \;
# 90日以上前の圧縮済みログを削除
find /var/log/app/ -name "*.log.gz" -mtime +90 -delete
echo "$(date '+%Y-%m-%d %H:%M:%S') - Log cleanup completed" >> /var/log/cleanup.log
ログの管理方法について詳しくはログ管理ガイドを参照してください。
サーバー監視とアラート通知
# 5分ごとにディスク使用率を確認し、閾値を超えたらアラート
*/5 * * * * /opt/scripts/disk-alert.sh
disk-alert.shの内容例:
#!/bin/bash
THRESHOLD=85
ALERT_EMAIL="admin@example.com"
df -h | awk 'NR>1 {gsub(/%/,"",$5); if($5 > '"$THRESHOLD"') print $0}' | while read line; do
echo "ディスク使用率警告: $line" | mail -s "[Alert] Disk usage over ${THRESHOLD}%" "$ALERT_EMAIL"
done
SSL証明書の有効期限チェック
# 毎日午前9時にSSL証明書の有効期限を確認
0 9 * * * /opt/scripts/ssl-check.sh
#!/bin/bash
DOMAIN="example.com"
DAYS_BEFORE=30
ALERT_EMAIL="admin@example.com"
expiry_date=$(echo | openssl s_client -connect "$DOMAIN:443" -servername "$DOMAIN" 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
expiry_epoch=$(date -d "$expiry_date" +%s)
current_epoch=$(date +%s)
days_left=$(( (expiry_epoch - current_epoch) / 86400 ))
if [ "$days_left" -lt "$DAYS_BEFORE" ]; then
echo "SSL証明書の有効期限が${days_left}日後に迫っています: $DOMAIN" | mail -s "[Alert] SSL Certificate Expiry" "$ALERT_EMAIL"
fi
cronのトラブルシューティング
cronは設定を間違えても即座にエラーが表示されないため、トラブルの原因特定が難しい場合があります。よくある問題と対処法を紹介します。
cronジョブが実行されない場合のチェックリスト
- cronデーモンが動作しているか確認
$ systemctl status cron
- crontabの書式が正しいか確認
$ crontab -l
- スクリプトに実行権限があるか確認
$ ls -la /path/to/script.sh
# 実行権限がない場合
$ chmod +x /path/to/script.sh
- コマンドのフルパスを使用しているか確認
cronはユーザーのシェル環境を読み込まないため、PATHが最小限しか設定されていません。コマンドはフルパスで記述するか、crontabの先頭でPATHを明示的に設定してください。
# PATHを明示的に設定
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# コマンドはフルパスで記述
0 3 * * * /usr/bin/python3 /opt/scripts/report.py
- cronログを確認
# Ubuntu/Debian
$ grep CRON /var/log/syslog | tail -20
# CentOS/Rocky Linux
$ grep CRON /var/log/cron | tail -20
# systemdのジャーナルで確認
$ journalctl -u cron --since "1 hour ago"
環境変数の問題
cronで最も多いトラブルの一つが環境変数の問題です。cronはユーザーの.bashrcや.profileを読み込まないため、シェルで動作するスクリプトがcronでは動かないことがあります。
# crontab内で環境変数を設定する方法
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
HOME=/home/tanaka
LANG=ja_JP.UTF-8
MAILTO=tanaka@example.com
0 3 * * * /opt/scripts/backup.sh
環境変数の仕組みを理解しておくと、cronのトラブル解決が格段にスムーズになります。
出力とエラーの処理
cronジョブの出力を適切に処理しないと、メールが大量に送信されたり、問題の検知が遅れたりします。
# 標準出力と標準エラー出力をファイルに記録
0 3 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# 標準出力は破棄し、エラーのみ記録
0 3 * * * /opt/scripts/backup.sh > /dev/null 2>> /var/log/backup-error.log
# 出力をすべて破棄(推奨しない:問題の検知が困難になる)
0 3 * * * /opt/scripts/backup.sh > /dev/null 2>&1
# メール通知(MAILTO設定)
MAILTO=admin@example.com
0 3 * * * /opt/scripts/backup.sh
cronの代替・補完ツール
cronは長い歴史を持つ信頼性の高いツールですが、用途によっては他のツールの方が適している場合もあります。
systemdタイマー
systemdにはタイマーユニットという機能があり、cronの代替として使用できます。systemdタイマーはcronにはない以下のメリットがあります。
- ジョブの依存関係を設定できる
- journalctlでログを統合管理できる
- 起動遅延のランダム化ができる(サーバー負荷の分散)
- リソース制限(CPU、メモリ)を設定できる
# タイマーユニットの例:/etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer
[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=300
Persistent=true
[Install]
WantedBy=timers.target
# 対応するサービスユニット:/etc/systemd/system/backup.service
[Unit]
Description=Daily Backup
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
User=backup
# タイマーの有効化
$ sudo systemctl enable --now backup.timer
# アクティブなタイマーの一覧
$ systemctl list-timers
systemdタイマーの詳細はsystemdサービス管理ガイドで解説しています。
anacronで実行漏れを防ぐ
anacronは、サーバーが停止していた間に実行されなかったジョブを、次回起動時に自動で実行する機能を持っています。cronは指定された正確な時刻にしか実行しないため、その時点でサーバーがダウンしていたジョブは永久にスキップされます。
# /etc/anacrontab の例
# 日数 遅延(分) ジョブ名 コマンド
1 5 daily-backup /opt/scripts/backup.sh
7 10 weekly-report /opt/scripts/weekly-report.sh
30 15 monthly-cleanup /opt/scripts/cleanup.sh
まとめ:cronを使いこなしてサーバー運用を自動化する
本記事では、Linuxのcronによる定期タスク実行の設定方法を解説しました。重要なポイントを振り返ります。
- crontabの書式:分・時・日・月・曜日の5フィールドで実行スケジュールを指定する
- crontab -eでユーザーごとのスケジュールを編集する
- フルパスでコマンドを記述し、環境変数を明示的に設定する
- 出力リダイレクトでログを適切に記録する
- %のエスケープを忘れない(crontab内では
\%) - 用途に応じてsystemdタイマーやanacronも検討する
cronの自動化はシェルスクリプトと組み合わせることで真価を発揮します。バックアップ、監視、レポート生成などの定型業務を自動化し、サーバー運用の効率を大幅に向上させましょう。
さらに、バックアップと復元やパフォーマンス監視のスクリプトをcronで定期実行することで、堅牢なサーバー運用体制を構築できます。
関連記事
AWS CloudFrontでサイト高速化|CDN設定からキャッシュ戦略まで実践解説
AWS CloudWatchで監視・アラート設定|運用担当者のための実践ガイド
AWS CodePipelineでCI/CD構築|コード変更から本番デプロイまでの自動化
AWS Cost Explorerでコスト可視化|ムダを見つけて月額費用を削減する実践術
AWS ECS/Fargateでコンテナ運用|Docker→本番デプロイの実践ガイド
AWS IAMのベストプラクティス|最小権限の原則を実務で実装する方法
AWS RDSの実務ガイド|データベース構築・バックアップ・パフォーマンスチューニング
AWS S3の実務活用ガイド|バケット設計・アクセス制御・コスト最適化の実践