概要
新しく導入したwheneverが、ステージング及び本番環境で実行されていなかったので原因・調査結果をまとめました。
状況
syslogを見ると、cron自体は実行されようとしているがNo MTA installed, discarding output
の文字が・・・。
$ grep CRON /var/log/syslog
Nov 1 XX:XX:XX XXXXXXXXXXXXXXXXXXXXX CRON[XXXXX]: (ubuntu) CMD (/bin/bash -l -c 'cd /srv/api/releases/XXXXXXXXXX && RAILS_ENV=staging bundle exec rake XXXX:XXXX --silent')
Nov 1 XX:XX:XX XXXXXXXXXXXXXXXXXXXXX CRON[XXXXX]: (CRON) info (No MTA installed, discarding output)
しかしshell上で同様のコマンドを打つと正常に動作します。
$ /bin/bash -l -c 'cd /srv/api/releases/XXXXXXXXXX && RAILS_ENV=staging bundle exec rake XXXX:XXXX --silent'
outputも出力されていないので、詳細がこれ以上わからないという状況でした。
set :output, "/path/to/my/cron_log.log"
原因
結論から書くと、cron実行時にPATH上にbundleが存在しないことが原因でした。
なぜこうなるの?
.profile
ではなく.bashrc
で設定されたパス上にbundleが存在するのが根本要因になります。
$ which bundle
$HOME/.rbenv/shims/bundle
$ grep PATH= ~/.profile
PATH="$HOME/bin:$HOME/.local/bin:$PATH"
$ grep PATH= ~/.bashrc
export PATH="$HOME/.rbenv/bin:$PATH"
まずcronは最初/usr/bin
と/bin
しか参照できない状態です。
そのためwheneverで設定されたcronは/bin/bash -l -c
上で実行されます。
-l
はログインした状態で実行されるため、.bash_profile|.bash_login|.profile
が呼び出されます。
しかし.bashrc
は呼び出されないため、環境変数が無いわけですね。
$ man bash
-l Make bash act as if it had been invoked as a login shell (see INVOCATION below).
つまり、何かしらの方法でcron実行時にbundleにPATHが通るようにする必要があるわけです。
対応方法
1. .bash_profile|.bash_login|.profile
上で環境変数の定義をする
一番ダイレクトな対応方針です。
一般的にも環境変数の定義はこちらですることが推奨されているように見えます。
2. cron実行時に環境変数を定義する
crontabが実行されてるときにPATHをセットしてしまおうってことですね。
$ grep PATH /etc/crontab
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
wheneverではshedule.rb
に下記コードを足すことでPATHを通すことができます。
env :PATH, ENV['PATH']
こちらについては下記スレッドに出てきている内容を参考にしました。
ref) Whenever gem (cron job) not executing rake task, Rails 4
3. jobを対話モードで実行する。
bash
を-i
で対話モードとして実行することで.bashrc
が読み込まれるようになります。
そのため.bashrc
に定義されたPATHが通るというわけですね。
set :job_template, "/bin/bash -l -i -c ':job'"
こちらについては下記スレッドに出てきている内容を参考にしました。
ref) Cron commands doesn't work in Ubuntu with 0.6.2 with rails3
おわりに
調べると英語圏で困ってる人がたくさんいるようだったものの、日本語記事があまりなさそうだったのでまとめてみました。
こういう問題は、わかるとシンプルでも、わかるまでは本当に意味不明なんですよね・・・。