cronがうまく動かなくて躓いた
やりたいこと
以下のことをしたかったがなんかcronが動かなくて躓いたのでメモ。
- Rubyで書いたスクリプトを手元のcronで動かしたい
- ArchLinux (cronie)
- natto, twitter Gemを使用
起こったこと
cronが動かないのでとりあえずログを見てみます。
journalctl | grep CRON Aug 24 13:02:01 Sirius CROND[17841]: (hsm-hx) CMD (ruby ~/programming/ruby/Twitter-managerbot/bot.rb) Aug 24 13:02:01 Sirius CROND[17838]: (hsm-hx) CMDOUT (/usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require': cannot load such file -- natto (LoadError)) Aug 24 13:02:01 Sirius CROND[17838]: (hsm-hx) CMDOUT ( from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require') Aug 24 13:02:01 Sirius CROND[17838]: (hsm-hx) CMDOUT ( from /home/hsm-hx/programming/ruby/Twitter-managerbot/bot.rb:1:in `<main>') Aug 24 13:02:01 Sirius CROND[17838]: pam_unix(crond:session): session closed for user hsm-hx
cronは回ってるけどnattoが読み込めずにLoadErrorを吐かれています。
いろいろネットで調べたところ、cronの実行時と普段使っているシェルでの実行時とで使われている環境変数が違うため、Ruby Gemにパスが通っていないことが原因のようです。
crontab -e
の中で環境変数を宣言したりすることもできるんですが、あれこれやってるとbashがないやらファイルが開けないやら怒られまくってよくわからなくなってしまった(環境変数PATH本当に難しい)。
解決した
解決策として、crontab -eに以下を記述しました。
*/20 * * * * /bin/zsh -lc 'ruby /path/to/script/bot.rb'
シェルを呼び出してそこからスクリプトを実行することで、シェルに設定している環境変数をそのまま使うことができました。
実はこれまで.zshenvと.zshrcの使い分けがわかっていなかったのですが、
.zshenvはzshそのものの起動時、.zshrcはインタラクティブシェルの起動時(で合ってる?)という違いがあることをこれを機に知りました。
今回の場合、起動されるのはインタラクティブシェルではないので、.zshenvに環境変数が書いてないとうまく実行されないはずです。
そもそも環境変数は.zshenvに、aliasとかzshプラグインのような操作に関わるものは.zshrcに書くらしいというのを初めて知りました。ひとつ賢くなりました(もし理解が違ってたら教えてください)。
まとめ
- cronとシェルの環境変数は別
- cronが動いてないときは
journalctl | grep CRON
でログ確認 - cron上でパスが通ってないときはシェルを通すといい感じになる
- 環境変数は.zshenvに置いておきましょう
cronのクローン
— はすみ (@hsm_hx) August 24, 2018