Table of Contents
はじめに
たまに書こうと思ったときに「どうするんだっけ?」となってしまう cronの書き方をまとめてみました。
cronの基本
# 編集crontab -e
# 確認だけしたいときcrontab -l基本書式
分 時 日 月 曜日 コマンドパス
- 分: 0~59
- 時: 0~23
- 日: 1~31
- 月: 1~12
- 曜日: 0~7(0:日, 1:月, 2:火, 3:水, 4:木, 5:金, 6:土, 7:日)
時間指定の例
- すべてを指定したい(毎時など):
* - 15分ごとに実行: 分部分で
0,15,30,45または*/15 - 月~金曜日で実行: 曜日部分で
1-5 - 1時、3時、20 ~ 23時で実行: 時間部分で
1,3,20-23 - 1時、3時、5時で実行: 時間部分で
1-5/2
(おまけ)複数コマンドを実行したい場合
;で区切る。
(おまけ)タイムゾーンを指定したい場合
サーバーのタイムゾーンに関係なく、cronを実行するときのタイムゾーンを指定できます。
CRON_TZ=Asia/Tokyo(おまけ)ログを出力したい場合
1が標準出力、2が標準エラー出力です。
>> /tmp/cron.log 2>&1例
毎日05:30(JST)に/home/hogeに移動後、get_huga.pyを実行し、
標準出力・標準エラー出力を/home/hoge/log/cron.logに記録する。
CRON_TZ=Asia/Tokyo30 5 * * * cd /home/hoge; python get_huga.py >> /home/hoge/log/cron.log 2>&1cron.d を使う
crontab -e で個人の設定として書く以外に、/etc/cron.d/ に設定ファイルを置く方法があります。設定を用途ごとにファイルで分けられるので、管理しやすくなります。
$ sudo vim /etc/cron.d/hoge書式はcrontabとほぼ同じですが、時間の次に実行ユーザーを指定する点が違います。
* * * * * root /home/hoge/script.shログを /var/log/cron.log に残したい場合は、rsyslogの設定でcronの行のコメントを外します。
$ sudo vim /etc/rsyslog.d/50-default.conf# 次の行の先頭の # を外すcron.* /var/log/cron.log設定後、両方を再起動します。
$ sudo service cron restart$ sudo service rsyslog restart$ service cron status動かないときに確認すること
cronは失敗しても何も教えてくれないので、原因を順に潰していきます。まずログを出す設定にするのが先決です。
/bin/sh: ~: not found が出る
**PATHが通っていないのが原因です。**cronは対話シェルとは別の最小限の環境で動くため、.bashrc で設定したPATHは引き継がれません。
シェルとスクリプトの両方を絶対パスで書きます。
* * * * * /bin/sh /home/hoge/script.shsh の場所が分からない場合は調べられます。
$ which sh同じ理由で、Pythonなどの実行ファイルも絶対パスで指定してください。仮想環境を使う場合は activate せず、venv内のPythonを直接呼びます。
* * * * * /home/hoge/venv/bin/python /home/hoge/app.py >> /tmp/cron.log 2>&1Permission denied が出る
スクリプトに実行権限がありません。
$ chmod +x script.sh手元では動くのにcronだと動かない
**BOM(Byte Order Mark)が入っている可能性があります。**Windowsのメモ帳で作成・編集したシェルスクリプトをLinuxに持ってくると、ファイル先頭に見えない文字が入り、1行目が正しく解釈されません。
Vimで確認できます。
# BOMの有無を確認する:set bomb?
# BOMを削除する:set nobomb同じ理由で改行コードにも注意してください。CRLFのままだと、行末の が引数の一部として扱われて失敗します。
# 改行コードを確認して LF にする:set fileformat?:set fileformat=unix環境変数が読めない
.bashrc や .profile で設定した変数は引き継がれません。スクリプト側で読み込む仕組みを用意してください。.env を読む方法はPythonのファイル・パス操作まとめに書いています。
% が使えない
cronでは % が特殊文字(改行)として扱われます。date +%Y%m%d のような書き方をする場合はエスケープが必要です。
0 5 * * * /bin/sh /home/hoge/backup.sh > /tmp/backup_$(date +\%Y\%m\%d).log 2>&1実行されたかを確認する
$ grep CRON /var/log/syslogcronが起動を試みたかどうかは、ここで分かります。ログに記録が無ければcron自体が動いていない、記録があるのに結果が出ていなければスクリプト側の問題、と切り分けられます。
