📝
コマンドをcronジョブにしたときのエラー
はじめに,背景
図書館で借りた本の期限をよく忘れてしまうため,
借りている本の情報をスクレイピングで取得してslackにリマインドする機能を作りました.
自宅で眠っていたラズパイがもったいないのでcronに設定したところ,
エラーで何度か失敗したので記録として残しておきます.
cronジョブの概要
定期実行したいコマンド
npx ts-node /home/uskemor/workspace/node.js/index.ts
ジョブの詳細
- 図書館サイトのマイページにログイン
- 借りている本の一覧を取得
- 本のタイトルと返却期限をwebhookでslackに通知
ジョブ実行環境
ハード: Raspberry Pi 3 Model B
OS: Raspberry Pi OS 64bit
Node.js: 18.18.0
npm: 10.2.0
ジョブ実行タイミング
毎日午前9時5分
発生したエラー
手動では動いたがcronジョブは失敗する
slackに通知が届いていないため調査開始.
syslog上にエラーの情報はなかったが,後続のinfoログを見る限りメールで通知しようとしていた節がある
(横着せずに標準エラーをリダイレクトしてファイルに残しておけばよかった)
/var/log/syslog
(uskemor) CMD (/home/uskemor/.nvm/versions/node/v18.18.0/bin/npx ts-node ~/workspace/node.js/index.ts)
(CRON) info (No MTA installed, discarding output)
エラー時のcron設定
5 9 * * * npx ts-node /home/uskemor/workspace/node.js/index.ts
原因
cron実行時に実行ユーザのPATHを参照していない
以下の通りcronジョブを設定して環境変数を確認したところ,PATHには``のみが登録されている.
~/.bashrc
は読み込まないようだ.
cron設定
* * * * * /usr/bin/env > /home/uskemor/env.txt
env.txt
PATH=/usr/bin:/bin
解消方法
- crontabにPATHを直接書き込む
修正後の設定
PATH=/home/uskemor/.nvm/versions/node/v18.18.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
5 9 * * * npx ts-node /home/uskemor/workspace/node.js/index.ts
(補足)「No MTA installed, discarding output」とは
メール送信のためのソフトが入っていないため,ジョブ実行時の結果を破棄したことを伝えている.
Raspberry Pi OSにはsendmailやpostfixが入っておらず,手動でインストールする必要がある.
dotenvによる.env読み込みに失敗している
エラー時の実装
index.ts
require('dotenv').config();
原因
.envファイルのパスを指定していないことで,
cronジョブ実行時に読み込み対象の.envファイルを見つけられなかった.
解消方法
config()に.envのパスを渡す.
修正後の実装
require('dotenv').config({ path: '/home/uskemor/workspace/node.js/.env' });
おわりに
この記事がいつか誰かの役に立てば幸いです.
数カ月後の自分かも?
参考リンク
stack overflow: Can't find dotenv environment variables from cron job
admin note: cron実行時の環境変数を設定
Discussion