3.

cron / crontab の書き方完全ガイド(書式・@reboot・環境変数・systemd timer 比較)

編集
この記事の要点
  • crontab -e で編集、crontab -l で確認、crontab -r で削除
  • 書式は 5 フィールド: 分 時 日 月 曜日 コマンド(曜日は 0=日〜6=土、または 7=日)
  • @reboot / @daily / @hourly / @weekly / @monthly の特殊指定が使える
  • cron は最小限の環境変数で動く → PATHSHELL を crontab 内で明示が必要
  • ログ出力は必ず >> /var/log/myapp.log 2>&1 でリダイレクト(無いと失敗を見逃す)

cron / crontab とは

Linux でコマンドやスクリプトを定期的に自動実行する仕組みです。バックアップ、ログローテーション、バッチ処理、メール送信、ヘルスチェック等に広く使われます。

  • cron: バックグラウンドで動く常駐サービス(デーモン)
  • crontab: cron に登録するジョブ定義テーブル

基本コマンド

# 自分の crontab を編集
crontab -e

# 自分の crontab を確認
crontab -l

# 自分の crontab を削除(確認なし!)
crontab -r

# 別ユーザの crontab を編集(要 root)
sudo crontab -e -u www-data

# システム共通の crontab(root 権限ジョブ)
sudo vi /etc/crontab

# /etc/cron.d/ にファイル単位で追加(推奨)
sudo vi /etc/cron.d/myapp

書式: 5 フィールド + コマンド

* * * * * コマンド
| | | | |
| | | | +-- 曜日 (0=日, 1=月, ... 6=土, 7=日 でも可)
| | | +---- 月 (1-12 または jan-dec)
| | +------ 日 (1-31)
| +-------- 時 (0-23)
+---------- 分 (0-59)

各フィールドで使える記法:

記法意味
*任意の値毎分 / 毎時
5具体的な値5 分
1,3,5列挙1,3,5 時
9-17範囲9 時から 17 時
*/1515 ずつ0,15,30,45 分
0-30/50-30 を 5 刻み0,5,10,15,20,25,30 分

よくある記述例

# 毎分実行
* * * * * /usr/local/bin/healthcheck.sh

# 毎時 0 分に実行(毎時 1 回)
0 * * * * /usr/bin/php /var/www/myapp/artisan queue:work --stop-when-empty

# 毎日 3:30 に実行
30 3 * * * /usr/local/bin/backup.sh

# 平日(月〜金)の朝 9 時
0 9 * * 1-5 /usr/local/bin/morning-report.sh

# 5 分おき
*/5 * * * * /usr/local/bin/heartbeat.sh

# 15 分おき、9-17 時の間だけ
*/15 9-17 * * * /usr/local/bin/poll.sh

# 毎月 1 日の 4:00 に
0 4 1 * * /usr/local/bin/monthly-cleanup.sh

# 毎週日曜の 2:00
0 2 * * 0 /usr/local/bin/weekly-report.sh

# 1, 15 日の 12:30
30 12 1,15 * * /usr/local/bin/biweekly.sh

特殊指定(@reboot / @daily 等)

# 再起動時に 1 回実行
@reboot /usr/local/bin/startup.sh

# 毎日 0:00 に(= 0 0 * * *)
@daily /usr/local/bin/daily.sh

# 毎時 0 分に(= 0 * * * *)
@hourly /usr/local/bin/hourly.sh

# 毎週日曜 0:00 に(= 0 0 * * 0)
@weekly /usr/local/bin/weekly.sh

# 毎月 1 日 0:00 に(= 0 0 1 * *)
@monthly /usr/local/bin/monthly.sh

# 毎年 1/1 0:00 に
@yearly /usr/local/bin/yearly.sh

環境変数の罠(最頻トラブル)

cron はログインシェルとは違う最小環境で動きます。PATH/usr/bin:/bin しかなかったり、HOME が想定と違ったり。これが「ターミナルでは動くのに cron だと動かない」の主原因です:

# crontab の先頭で環境変数を明示
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/home/myuser
MAILTO=admin@example.com           # 出力があればメール送信

# ジョブ
0 3 * * * /usr/local/bin/backup.sh

またはコマンド側で絶対パスを使う:

# ❌ NG(PATH に /usr/local/bin が無いと失敗)
0 3 * * * mycommand

# ✅ OK
0 3 * * * /usr/local/bin/mycommand

# Laravel Schedule の標準形
* * * * * cd /var/www/myapp && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

ログ出力(必須)

cron の標準出力 / エラーはそのままだとメールで送られる(MAILTO 未設定なら捨てられる)ため、ログファイルに出すのが定番です:

# 標準出力をログに(標準エラーは捨て)
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log

# 標準出力もエラーもログに(推奨)
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

# 出力を全部捨てる(メールも来なくする)
0 3 * * * /usr/local/bin/backup.sh > /dev/null 2>&1

# Laravel scheduler 標準形
* * * * * cd /var/www/myapp && php artisan schedule:run >> /var/log/laravel-schedule.log 2>&1

動作確認方法

# cron デーモンが動いているか
sudo systemctl status cron        # Debian/Ubuntu
sudo systemctl status crond       # CentOS/RHEL

# 実行ログ確認
sudo grep CRON /var/log/syslog | tail -20            # Ubuntu
sudo tail -f /var/log/cron                           # CentOS

# 一時的に毎分実行に変えてテスト
* * * * * /usr/local/bin/myjob.sh >> /tmp/test.log 2>&1

# 手動で同じ環境で実行してデバッグ
env -i HOME=$HOME PATH=/usr/bin:/bin SHELL=/bin/bash /usr/local/bin/myjob.sh

/etc/cron.d/ で管理(推奨パターン)

個人 crontab だと書いた人にしか分からないため、本番では /etc/cron.d/ にアプリ別ファイルで置くのが運用上推奨されます:

# /etc/cron.d/myapp
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# 6 フィールド: 分 時 日 月 曜日 ユーザ コマンド
* * * * * www-data cd /var/www/myapp && php artisan schedule:run >> /var/log/myapp.log 2>&1
0 3 * * * www-data /usr/local/bin/backup-myapp.sh

個人 crontab と違いユーザ名フィールドが必須です(5 番目と 6 番目の間)。

systemd timer(cron の代替)

近年は systemd timer が増えています。利点: 詳細なログ、依存関係、リトライ等:

# /etc/systemd/system/backup.service
[Unit]
Description=Daily backup

[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/backup.sh

# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup.service daily at 03:30

[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true       # 起動時に未実行分を実行

[Install]
WantedBy=timers.target
# 有効化
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

# タイマー一覧
systemctl list-timers
systemctl list-timers --all

# 個別の実行履歴
journalctl -u backup.service

cron vs systemd timer

項目cronsystemd timer
導入の手軽さ△(2 ファイル必要)
ログsyslog のみjournald で詳細
失敗時のリトライ無しRestart=on-failure
依存関係無しAfter= / Requires=
稼働中マシンの寝起き対応無しPersistent=true で未実行分を即実行
記述量1 行2 ファイル

よくあるトラブル

症状原因対処
登録したが動かないcron デーモン未起動sudo systemctl start cron
ターミナルでは動くが cron だと動かないPATH が違う絶対パス or PATH 指定
「コマンド not found」同上同上
出力が見えないリダイレクト無し>> log 2>&1
パーセント記号で切れるcron で % は改行扱い\% でエスケープ
日と曜日両方指定 → OR「日 OR 曜日」が成立意図と違うと壊れる

FAQ

Q: 13 * * * 1 は「毎時 13 分、月曜だけ」?
A: 違います。「毎時 13 分」または「月曜 0 分」のいずれかで実行されます(日と曜日は OR 関係)。意図的に「月曜の 13 分」にしたいなら 13 * * * 1 + シェルスクリプト内で曜日チェックが安全。

Q: 秒単位の実行はできる?
A: 標準 cron は最小 1 分。秒単位は while true; do ...; sleep 10; done をデーモンで動かすか、systemd の OnUnitActiveSec=10s を使います。

Q: 古い crontab を上書きしてしまった
A: バックアップ習慣をつけてください。crontab -l > ~/crontab.bak.$(date +%F)@daily で自動取得しておくのが定石です。

Q: Docker コンテナ内で cron を動かしたい
A: 公式イメージは cron が入っていないので apt install cron + フォアグラウンドで cron -f 起動。ただし Docker では「1 コンテナ 1 プロセス」原則に従い、ホスト側 crondocker exec ベースが推奨です。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. ls ファイル/ディレクトリ一覧表示
  2. sudo ユーザー指定
  3. cron/crontab ジョブの自動実行と登録方法
  4. wget http通信によるファイルダウンロード
  5. rm ファイル/ディレクトリ削除
  6. pwd カレントディレクトリの表示
  7. cd ディレクトリの移動
  8. ./configure
  9. make
  10. make install
  11. unzip ファイルの解凍
  12. mv ファイル/ディレクトリの移動および名称変更
  13. mkdir ディレクトリの作成
  14. touch 空ファイルの新規作成
  15. vi テキストディタの使用
  16. find ファイル/ディレクトリ検索
  17. grep 文字列の検索
  18. tail ファイルの末尾表示
  19. curl HTTP通信によるリクエスト
  20. nslookup ドメインのIP解決
  21. apt update パッケージリストの情報を更新
  22. apt upgrade パッケージの更新
  23. ln リンク/ショートカットの作成と削除
  24. rsync ファイル/ディレクトリの同期
  25. ssh リモートとの暗号化通信
  26. scp sshを利用したファイルのコピー
  27. unzip zip ファイルを解凍する
  28. cp ファイル/ディレクトリのコピー
  29. diffファイルの差分抽出
  30. fdisk ハードディスクに対する操作
  31. lsblk デバイスをツリー状で表示する
  32. kill プロセスを終了させる
  33. zip ファイルやディレクトリをzip形式に圧縮する
  34. host ドメインからIPアドレスを確認
  35. chmod 権限の変更
  36. ip IPアドレスの確認
  37. chown ファイル/ディレクトリ所有者の変更
  38. chgrp ファイル/ディレクトリのグループ情報の変更
  39. nohupと'&' プログラムのバックグラウンド実行(ssh接続時)
  40. lsof 開いているポート番号の確認
  41. tar ファイルの圧縮と解凍
  42. file ファイルの種類を表示
  43. cat ファイルの中身を表示
  44. head ファイルの先頭部分を表示
  45. wc 行数/単語数/文字数を確認
  46. shutdown システムのシャットダウンと再起動
  47. ps プロセスの確認
  48. which コマンドの絶対パスを調べる
  49. yum RedHat系ディストリビューションの管理
  50. mount ファイルシステムのマウント
  51. 特定フォルダ以下の特定拡張子のファイルを再帰的に削除する方法
  52. 特定のフォルダとそのサブフォルダ内にある特定のファイル名のファイルを再帰的に削除