📝

コマンドをcronジョブにしたときのエラー

2023/10/10に公開

はじめに,背景

図書館で借りた本の期限をよく忘れてしまうため,
借りている本の情報をスクレイピングで取得してslackにリマインドする機能を作りました.
自宅で眠っていたラズパイがもったいないのでcronに設定したところ,
エラーで何度か失敗したので記録として残しておきます.

cronジョブの概要

定期実行したいコマンド

npx ts-node /home/uskemor/workspace/node.js/index.ts

ジョブの詳細

  1. 図書館サイトのマイページにログイン
  2. 借りている本の一覧を取得
  3. 本のタイトルと返却期限を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