skip to content
barorin&

cronの書き方とトラブル対処|書式・cron.d・動かないときの確認

/ 6 min read

Updated:
Table of Contents

はじめに

たまに書こうと思ったときに「どうするんだっけ?」となってしまう cronの書き方をまとめてみました。

cronの基本

Terminal window
# 編集
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に記録する。

Terminal window
CRON_TZ=Asia/Tokyo
30 5 * * * cd /home/hoge; python get_huga.py >> /home/hoge/log/cron.log 2>&1

cron.d を使う

crontab -e で個人の設定として書く以外に、/etc/cron.d/ に設定ファイルを置く方法があります。設定を用途ごとにファイルで分けられるので、管理しやすくなります。

Terminal window
$ sudo vim /etc/cron.d/hoge

書式はcrontabとほぼ同じですが、時間の次に実行ユーザーを指定する点が違います。

Terminal window
* * * * * root /home/hoge/script.sh

ログを /var/log/cron.log に残したい場合は、rsyslogの設定でcronの行のコメントを外します。

Terminal window
$ sudo vim /etc/rsyslog.d/50-default.conf
Terminal window
# 次の行の先頭の # を外す
cron.* /var/log/cron.log

設定後、両方を再起動します。

Terminal window
$ sudo service cron restart
$ sudo service rsyslog restart
$ service cron status

動かないときに確認すること

cronは失敗しても何も教えてくれないので、原因を順に潰していきます。まずログを出す設定にするのが先決です。

/bin/sh: ~: not found が出る

**PATHが通っていないのが原因です。**cronは対話シェルとは別の最小限の環境で動くため、.bashrc で設定したPATHは引き継がれません。

シェルとスクリプトの両方を絶対パスで書きます。

Terminal window
* * * * * /bin/sh /home/hoge/script.sh

sh の場所が分からない場合は調べられます。

Terminal window
$ which sh

同じ理由で、Pythonなどの実行ファイルも絶対パスで指定してください。仮想環境を使う場合は activate せず、venv内のPythonを直接呼びます。

Terminal window
* * * * * /home/hoge/venv/bin/python /home/hoge/app.py >> /tmp/cron.log 2>&1

Permission denied が出る

スクリプトに実行権限がありません。

Terminal window
$ chmod +x script.sh

手元では動くのにcronだと動かない

**BOM(Byte Order Mark)が入っている可能性があります。**Windowsのメモ帳で作成・編集したシェルスクリプトをLinuxに持ってくると、ファイル先頭に見えない文字が入り、1行目が正しく解釈されません。

Vimで確認できます。

Terminal window
# BOMの有無を確認する
:set bomb?
# BOMを削除する
:set nobomb

同じ理由で改行コードにも注意してください。CRLFのままだと、行末の が引数の一部として扱われて失敗します。

Terminal window
# 改行コードを確認して LF にする
:set fileformat?
:set fileformat=unix

環境変数が読めない

.bashrc.profile で設定した変数は引き継がれません。スクリプト側で読み込む仕組みを用意してください。.env を読む方法はPythonのファイル・パス操作まとめに書いています。

% が使えない

cronでは % が特殊文字(改行)として扱われます。date +%Y%m%d のような書き方をする場合はエスケープが必要です。

Terminal window
0 5 * * * /bin/sh /home/hoge/backup.sh > /tmp/backup_$(date +\%Y\%m\%d).log 2>&1

実行されたかを確認する

Terminal window
$ grep CRON /var/log/syslog

cronが起動を試みたかどうかは、ここで分かります。ログに記録が無ければcron自体が動いていない、記録があるのに結果が出ていなければスクリプト側の問題、と切り分けられます。

この記事を書いた人

barorinのプロフィール画像

barorin公認会計士

会計とITの二足のわらじで働く公認会計士です。Pythonを中心に、会計・監査の実務で実際に使っているコードや、Ubuntu・Raspberry Piの設定メモを書いています。