crontab
cronは大抵標準で入っていて特殊な設定も特になく使えるので便利ですが、コマンド実行時に通常のshellで読み込まれている環境変数が読み込まれません。
crontabの設定ファイル内で変数の指定が出来ますが、いちいち別箇所に定義してやるのも面倒。
なので
* * * * * /bin/bash -l ruby script.rb
としてやれば、通常のlogin shellと同様に実行出来ます。
rubyのscript内で
require 'activerecord'
require 'erb'
config = YAML.load(ERB.new(File.read('/path/to/config/database.yml')).result)
ActiveRecord::Base.establish_connection(config['production'])
とかしてyml内の<%= SOME_VARIABLE %>
を読みだしていたのですが、環境変数が読み込まれていないためlocalhostに接続しようとして
Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) (Mysql2::Error)
が出ていました。何故ローカルホスト…?となってconfigをcron内で読み出すと接続情報がnilになっていて、それに気付くまで少しハマりました。
余談: cronのログ出力
初めは面倒で> /dev/null 2>&1
してログを破棄していたのですが、コケたとしても何も残らない為デバッグの初動が遅れます。
と言うかログを捨てていたせいで何故動いていないのか(通常のshellだと動くので)に気付くまで時間がかかりました。
* * * * * ruby script.rb 1>> /path/to/log/acript.log 2>> /path/to/log/script_err.log
としておけば 1>>
で標準出力が2>>
でエラー出力が残ります。
こう言うの大事。
参考にしたリンク
“/usr/bin/env bash” is not found when running from a cron script
crontabでrbenvのrubyを使う
crontabからrvmとbundlerを使う
crontabがどうしても動かないときに確認すべき3つの点+α
cron力をつけよう!全てのcrontab入門者に贈る9個のテクニック
crontabの使い方
cron(crontab)の簡単な使い方
cron 実行時にログインシェル(bash)と同じ環境変数で動かしたい