树莓派下通过Cron调用Shell脚本执行npm命令的故障排查
树莓派通过Cron调用Shell脚本启动Node.js应用的问题
操作场景
我在树莓派上编写Shell脚本,希望通过Cron定时调用它来启动基于npm管理的Node.js应用,但执行时遇到了环境变量缺失、命令找不到、日志覆盖等问题。
初始配置
- start.sh脚本(本地执行
./start.sh可正常运行,已通过which npm确认bash和npm路径正确):
#!/bin/bash #!/usr/local/bin/npm cd /home/lharby/sites/mysite npm run start
- Cron任务配置:
*/5 * * * * /home/lharby/sites/mysite/start.sh >> /home/lharby/sites/mysite/src/log/cron-errors.txt 2>&1
- Node.js代码中的环境变量依赖:
const config = { access_token: process.env.NEXT_MASTODON_ACCESS_TOKEN, client_key: process.env.NEXT_MASTODON_CLIENT_KEY, client_secret: process.env.NEXT_MASTODON_CLIENT_SECRET, timeout_ms: 60 * 1000, api_url: 'https://botsin.space/api/v1/', }; const M = new Mastodon(config);
- package.json脚本配置:
"scripts": { "start": "node ./src/index.js --experimental-modules", "temp": "node ./src/temp.js --experimental-modules" },
错误信息
从cron-errors.txt中提取的报错:
/home/lharby/sites/mysite/node_modules/mastodon-api/lib/mastodon.js:345 throw new Error('Mastodon config must include \'' + reqKey + '\' when using \'user_auth\''); ^ Error: Mastodon config must include 'access_token' when using 'user_auth' at /home/lharby/sites/glyphbot/node_modules/mastodon-api/lib/mastodon.js:345:27 // // /home/lharby/sites/mysite/start.sh: line 4: npm: command not found /bin/sh: 1: /home/sites/glyphbot/start.sh: not found /bin/sh: 1: /home/sites/glyphbot/start.sh: not found
后续尝试(19.01.23更新)
- 将环境变量添加到
.bashrc,终端执行echo $NEXT_MASTODON_ACCESS_TOKEN可正常显示值 - 更新
start.sh脚本:
#!/bin/bash node ./src/index.js --experimental-modules
- 更新Cron任务:
*/5 * * * * /home/lharby/sites/mysite/start.sh >> /home/lharby/sites/mysite/src/log/cron-errors.txt 2>&1
- 尝试跳过脚本直接执行Cron任务:
*/5 * * * * /home/lharby/sites/mysite/src && /usr/local/bin/node index.js --experimental-modules >>/home/lharby/sites/mysite/src/log/cron-errors.txt 2>&1
以上操作均未解决问题,终端直接执行脚本或node index.js --experimental-modules正常,但Cron执行仍报环境变量缺失。
核心问题
- 如何通过Cron调用npm运行Node项目?
- Cron能否获取npm命令中的环境变量?
>> cron-errors.txt 2>&1是否应追加日志而非覆盖?
解决方案
问题1:Cron调用npm运行Node项目的正确方式
Cron的环境变量PATH比终端窄很多,直接用npm会触发"命令找不到"错误,必须使用绝对路径:
- 先通过终端执行
which npm获取绝对路径(示例:/usr/local/bin/npm) - 修改start.sh脚本,移除多余的
#!/usr/local/bin/npm(脚本只能保留第一行的shebang#!/bin/bash),并使用npm绝对路径:
#!/bin/bash cd /home/lharby/sites/mysite /usr/local/bin/npm run start
- 或者直接在Cron任务中指定路径执行:
*/5 * * * * cd /home/lharby/sites/mysite && /usr/local/bin/npm run start >> /home/lharby/sites/mysite/src/log/cron-errors.txt 2>&1
问题2:Cron获取环境变量的方法
Cron不会加载.bashrc(仅交互式Shell会加载该配置),需手动导入环境变量,推荐三种方法:
方法1:在Shell脚本中直接导出变量
在start.sh开头添加环境变量定义:
#!/bin/bash export NEXT_MASTODON_ACCESS_TOKEN="你的token值" export NEXT_MASTODON_CLIENT_KEY="你的key值" export NEXT_MASTODON_CLIENT_SECRET="你的secret值" cd /home/lharby/sites/mysite /usr/local/bin/npm run start
方法2:在Cron中加载环境配置文件
如果变量存在.bash_profile或自定义的.env文件中,可在Cron任务中先加载:
*/5 * * * * source /home/lharby/.bash_profile && cd /home/lharby/sites/mysite && /usr/local/bin/npm run start >> /home/lharby/sites/mysite/src/log/cron-errors.txt 2>&1
方法3:使用Node.js的dotenv包(最可靠)
在项目中安装dotenv:
npm install dotenv
在index.js开头添加:
require('dotenv').config()
在项目根目录创建.env文件:
NEXT_MASTODON_ACCESS_TOKEN=你的token值 NEXT_MASTODON_CLIENT_KEY=你的key值 NEXT_MASTODON_CLIENT_SECRET=你的secret值
这种方式不依赖Shell环境变量,Node.js会直接读取.env文件内容。
问题3:日志追加而非覆盖的问题
>>确实是追加模式,出现覆盖的原因可能是:
- 日志文件所在目录不存在(比如
src/log未创建),导致Cron每次执行时创建新文件,先执行mkdir -p /home/lharby/sites/mysite/src/log确保目录存在。 - 脚本或应用代码中存在其他修改该日志文件的逻辑,检查相关代码是否有覆盖文件的操作。
内容的提问来源于stack exchange,提问作者lharby
相关产品推荐
相关产品推荐

