Bash 入門

Linux 定時タスク:cron と crontab による自動スケジューリング

cron は、Unix系オペレーティングシステムにおける時間ベースのタスクスケジューラです。特定の時間、日付、または時間間隔を設定することで、タスクを自動的に実行できます。これはシステム管理、データバックアップ、レポート生成、およびその他多くのオートメーションプロセスにおいて極めて有用です。cron があれば、手動で繰り返しスクリプトやコマンドを実行する必要はありません。人間の介入なしに、タスクが常に一貫して信頼性高く実行されるよう管理してくれます。

1. cron と crontab の理解

cron 自体はバックグラウンドで動作するデーモン(daemon)であり、定期的(通常は1分ごと)に起動して、実行すべきスケジュール済みのタスクがあるかどうかを確認します。

これらのタスクの実行スケジュールは、crontab(cron table、つまり cron 計画表)と呼ばれるファイルに保存されます。システム上の各ユーザーは、自身のユーザーアカウント専用のタスクをスケジュールするための独自の crontab ファイルを持つことができます。一方、システムレベルのタスクは通常、システムのグローバルな crontab に設定され、これらのファイルを修正するには通常 root(管理者)権限が必要です。

2. crontab の構文ルール

crontab ファイル内の各行は単一の cron タスクを表し、特定の構文に従います。この構文は6つのフィールドで構成されています。

分 時 日 月 曜日 コマンド

各フィールドを詳しく見ていきましょう:

  • 分 (minute): タスクを実行する分。範囲は 0-59。
  • 時 (hour): タスクを実行する時。範囲は 0-23。
  • 日 (day_of_month): タスクを実行する月の日。範囲は 1-31。
  • 月 (month): タスクを実行する月。範囲は 1-12(または Jan-Dec)。
  • 曜日 (day_of_week): タスクを実行する曜日。範囲は 0-6(または Sun-Sat。0 は日曜日)。
  • コマンド (command): 実行するコマンド。シンプルなシステムコマンドや、特定のスクリプトのアブソリュートパス(絶対パス)を指定できます。

また、さまざまな特殊記号を使用して異なるスケジュールパターンを指定できます:

  • * (アスタリスク): そのフィールドのすべての可能な値を表します。例えば、分フィールドが * であれば「毎分」を意味します。
  • , (カンマ): 値のリストを指定します。例えば、分フィールドに 1,15,30 と書くと、1分、15分、30分に実行されます。
  • - (ハイフン): 値の範囲を指定します。例えば、時フィールドに 8-17 と書くと、午前8時から午後5時まで1時間おきに実行されます。
  • / (スラッシュ): ステップ値を指定します。例えば、分フィールドに */15 と書くと、15分ごとに実行されます。

2.1 よく使われる crontab 設定例

以下は、一般的な crontab エントリとその意味です:

  • 0 0 * * * /path/to/backup_script.sh:毎日深夜(00:00)に backup_script.sh を実行します。
  • */5 * * * * /path/to/check_disk_space.sh:5分ごとに check_disk_space.sh を実行します。
  • 0 8 * * 1-5 /path/to/generate_report.sh:平日の月曜日から金曜日まで、毎朝8時に generate_report.sh を実行します。
  • 0 12 1 * * /path/to/monthly_cleanup.sh:毎月1日の正午12時に monthly_cleanup.sh を実行します。
  • 30 6 15 4 * /path/to/send_reminder.sh:4月15日の午前6:30に send_reminder.sh を実行します。

3. crontab の常用操作コマンド

crontab コマンドを使用して、定時タスクリストを管理できます。

3.1 スケジュール済みタスクの表示

現在のスケジュール表を確認するには、以下のコマンドを使用します:

crontab -l

これにより crontab ファイルの内容が表示され、スケジュールされているすべてのタスクがリストアップされます。タスクが設定されていない場合は、通常「no crontab for [ユーザー名]」と出力されます。

3.2 タスクスケジュール表の編集

スケジュール表を編集するには、以下のコマンドを使用します:

crontab -e

これにより、テキストエディタ(システム設定によりますが、通常は vinano)で crontab ファイルが開かれます。エントリの追加、修正、削除が可能です。ファイルを保存して閉じると、cron は自動的に新しいスケジュールを適用します。

例: /home/user/scripts/ ディレクトリにある monitor_system.sh を毎時30分に実行したい場合、スケジュール表に以下の1行を追加します。

30 * * * * /home/user/scripts/monitor_system.sh

3.3 すべてのタスクの削除

すべての cron タスクを消去するには、以下のコマンドを使用します:

crontab -r

これにより crontab ファイルが完全に削除されます。すべてのスケジュールタスクが消去されるため、このコマンドの使用には十分注意してください。システムによっては、実行時に確認メッセージが表示される場合があります。

4. ユーザーレベルとシステムレベルの定時タスク

前述の通り、各ユーザーは独自の crontab ファイルを持ち、上記の crontab コマンドで管理します。

一方で、システムレベルの cron タスクは通常、特定のディレクトリに配置されます。例えば、/etc/cron.d//etc/cron.hourly/(毎時)、/etc/cron.daily/(毎日)、/etc/cron.weekly/(毎週)、/etc/cron.monthly/(毎月)などです。

システムレベルのタスクを変更するには通常 root 権限が必要です(例:sudo の使用)。例えば、/etc/cron.daily/ ディレクトリにファイルを作成して、日常的なメンテナンススクリプトを実行できます。これらのディレクトリに保存されたファイルは、cron によって指定された頻度で自動的に実行されます。

例: システムレベルの毎日実行タスクを作成するには、/etc/cron.daily/my_daily_backup という名前のスクリプトを作成し、内容は以下の通りにします:

#!/bin/bash
# このスクリプトは重要なデータの毎日バックアップを作成します
tar -czvf /var/backups/my_data_$(date +%Y-%m-%d).tar.gz /path/to/my/data

このスクリプトに実行権限を付与することを忘れないでください:

sudo chmod +x /etc/cron.daily/my_daily_backup

これで、このスクリプトは毎日自動的に実行されるようになります。

5. cron タスク作成のベストプラクティス

cron を使用する際、いくつかのベストプラクティスに従うことが重要です。これによりタスクの信頼性を確保し、一般的なトラブルを回避できます。

5.1 アブソリュートパス(絶対パス)の使用

crontab のエントリでは、常にコマンドとスクリプトアブソリュートパスを使用してください。これにより、現在のワーキングディレクトリがどこであっても、cron が正確に実行ファイルを見つけることができます。cron 実行時の環境変数は非常に限定的であるため、$PATH に過度に依存すると「コマンドが見つかりません」というエラーが発生しやすくなります。

例: 単に backup_script.sh と書くのではなく、フルパスの /home/user/scripts/backup_script.sh と記述すべきです。

5.2 環境変数の設定

cron タスクは極めて最小限の環境(エンバイロメント)で実行されるため、インタラクティブなターミナルで使用できる環境変数cron タスクで利用できるとは限りません。スクリプトが特定の環境変数に依存している場合は、crontab ファイルの上部またはスクリプト内部で明示的に定義する必要があります。

例:

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 0 * * * /path/to/script.sh

ここでは、スクリプトが正しく実行されるように SHELLPATH バリアブルを明示的に定義しています。

5.3 出力のリダイレクト

デフォルトでは、cron はタスクから生成された出力(標準出力および標準エラー)をユーザーのローカルメールアカウントに送信します。タスクが大量のログを生成する場合、すぐにインボックスがいっぱいになってしまいます。これを避けるために、出力をログファイルリダイレクトするか、出力が不要な場合は /dev/null に破棄することをお勧めします。

例:

  • 標準出力のみをファイルにリダイレクト: 0 0 * * * /path/to/script.sh > /path/to/output.log
  • 標準エラーのみをファイルにリダイレクト: 0 0 * * * /path/to/script.sh 2> /path/to/error.log
  • 標準出力と標準エラーをマージしてファイルにリダイレクト: 0 0 * * * /path/to/script.sh > /path/to/output.log 2>&1
  • すべての出力を破棄: 0 0 * * * /path/to/script.sh > /dev/null 2>&1

5.4 エラーハンドリング、ログ、セキュリティ

  • エラーハンドリング: スクリプト内で適切なエラーハンドリングロジックを実装してください。これには、エラーのチェック、エラーログの記録、および適切な対応(アラートメールの送信など)が含まれます。
  • ログ記録: スクリプト内で重要なイベントやエラーを記録してください。これは問題のトラブルシューティングやオートメーションタスクの健康状態の監視に大きく役立ちます。
  • セキュリティ対策: cron タスクとしてスクリプトを実行することによるセキュリティ上の影響に注意してください。crontab ファイルやスクリプト内にパスワードなどの機密情報を平文で保存しないでください。適切なファイル権限を設定し、他人が許可なくスクリプトを修正できないようにしてください。

5.5 テスト

cron タスクを本番環境(プロダクション)にデプロイする前に、必ず徹底的なテストを行ってください。まず手動でスクリプトを実行してテストするか、cron で非常に短い間隔(例えば毎分)を設定して、自動実行の様子を観察してください。

6. cron 進階テクニック

基本的な時間のスケジューリング以外にも、cron は複雑なシナリオで役立ついくつかの高度な機能を提供しています。

6.1 @reboot の使用

@reboot 指令を使用すると、システムの起動(ブート)のたびにタスクを実行できます。これは、再起動後に必ず実行する必要がある操作、例えば特定のカスタムサービスの開始や、いくつかの設定の初期化に非常に便利です。

例:

@reboot /path/to/startup_script.sh

6.2 名前付きパイプ (FIFOs) との組み合わせ

cron タスクのより複雑なインタラクションが必要な場合は、名前付きパイプ(FIFOs)を使用できます。FIFO を使用すると、実行中の cron タスクと他のプロセス間でデータをやり取りできます。

例:

  1. FIFO を作成:mkfifo /tmp/my_fifo
  2. cron タスクで、データを FIFO に書き込む:/path/to/script.sh > /tmp/my_fifo
  3. 別のプロセスで、FIFO からデータを読み込む:cat /tmp/my_fifo

これにより、バックグラウンドの cron タスクからの出力をリアルタイムで受信できます。

6.3 Anacron の理解

cron は常に電源が入っているサーバーに最適です。一方で、anacron はノートパソコンや個人のデスクトップPCのように、頻繁に電源をオフにするシステム向けに設計されています。anacron は、予定されたタスクの実行時間にシステムがシャットダウンしていても、起動後の特定の周期(毎日、毎週、毎月など)でタスクが「補完」実行されることを保証します。これは cron の直接の代替品ではなく、補完的なツールです。anacron の詳細な解説は本章の範囲外ですが、その存在を知っておくことは有用です。

7. 実戦ケース:自動システム巡回とアラート

自動システム管理の実戦ケースを振り返ってみましょう。ディスクスペースの使用状況を自動的にチェックし、使用率が特定のしきい値を超えたときにアラートメールを送信したいとします。

まず、チェック用スクリプト (check_disk_space.sh) を作成します:

#!/bin/bash
# ディスク使用率のアラートしきい値を設定(パーセンテージ)
THRESHOLD=80 

# 現在のルートディレクトリのディスク使用率を取得(パーセント記号を削除)
USAGE=$(df -h / | awk 'NR==2 {print $5}' | tr -d '%') 

# 使用率がしきい値を超えているかチェック
if [ "$USAGE" -gt "$THRESHOLD" ]; then
  # 現在のホスト名を取得
  HOSTNAME=$(hostname)
    
  # メールのサブジェクトを設定
  SUBJECT="ディスクスペースアラート:$HOSTNAME"
    
  # メールの本文を設定
  BODY="$HOSTNAME 上のディスク使用率が現在 $USAGE% に達しました。至急確認してください。"
    
  # メールを送信
  echo "$BODY" | mail -s "$SUBJECT" [email protected]
fi

スクリプトに実行権限を付与します:

chmod +x check_disk_space.sh

cron を使用して、このスクリプトを1時間おきに実行するようにスケジュールします:

crontab -e

開いた crontab ファイルに以下の行を追加します:

0 * * * * /path/to/check_disk_space.sh

これで、このスクリプトは1時間ごとに自動実行され、ディスクの空き容量をチェックします。使用率が 80% を超えると、自動的に [email protected] へ警告メールが送信されます。例の中の /path/to/check_disk_space.sh は、実際のスクリプトアブソリュートパスに置き換えるのを忘れないでください。

この実戦ケースでは、これまでに学んだ知識を組み合わせています:cron によってスケジュールされた自動化スクリプトの中で、バリアブル、条件分岐、および出力の抽出を総合的に活用しています。