如何通过cron job执行Node.js脚本?

90
简单来说,我有一个Node脚本,希望每个月执行一次。
30 6 1 * * node /home/steve/example/script.js

但这并不起作用,可能是由于路径或执行该命令的shell。我尝试了以下几种通过cron执行node的方法(已通过-v测试):

steve@atom:~$ node -v
v0.4.2

steve@atom:~$ sh node -v
sh: Can't open node

steve@atom:~$ bash node -v
/usr/local/bin/node: /usr/local/bin/node: cannot execute binary file

steve@atom:~$ /usr/local/bin/node -v
v0.4.2

steve@atom:~$ sh /usr/local/bin/node -v
/usr/local/bin/node: 1: Syntax error: "(" unexpected

steve@atom:~$ bash /usr/local/bin/node -v
/usr/local/bin/node: /usr/local/bin/node: cannot execute binary file

我已经没有尝试的想法了,有什么建议吗?


1
阅读此链接 https://github.com/wahengchang/nodejs-cron-job-must-know ('nodejs-cron-job-must-know' 部分)。需要使用 cd 命令导航到脚本所在的目录。 我尝试了许多东西,但只有在这之后它才开始工作。 - Chaki_Black
10个回答

130

只需在您的cron作业中提供节点的完整路径/usr/local/bin/node,如下所示:

30 6 1 * * /usr/local/bin/node /home/steve/example/script.js

7
原文:It turned out to be a couple of problems, the full path as you said fixed the cron, but relative paths in the script were also a issue.翻译:事实证明有两个问题,就像你说的完整路径修复了cron,但脚本中的相对路径也是一个问题。 - Steve
@Steve 我正在使用config模块(例如require('config').DB),当通过crontab运行时,配置变量未被填充。 - codecowboy
29
警告!如果您使用nvm或n管理node安装,将/usr/local/bin/node放入可能无法正常工作!为了获取node的实际路径,请使用which node - 然后将该路径放在您的脚本之前。例如,我正在使用来自nvm的node 0.10.32,因此我的node路径是:/home/username/.nvm/v0.10.32/bin/node - YemSalat
1
@YemSalat 最好以节点版本无关的方式声明:#文档需要启用cronjob的node / nvm() #文档cron默认使用短路径= / usr / bin:/ bin,并且不执行/ root / .bashrc(等同于/ root / .bashrc) #文档nvm(节点版本管理器)不会在crontab作业中配置自己(仅在我的/ root / .bashrc中为交互式shell执行此操作)。 export NVM_DIR =“/ root / .nvm” [ -s“$ NVM_DIR / nvm.sh”] &&。 “$ NVM_DIR / nvm.sh”#这将加载nvm - Rolf
1
谢谢!如果您想要集成nvm,这里有一个示例:https://gist.github.com/simov/cdbebe2d65644279db1323042fcf7624 - ifthenelse
显示剩余3条评论

61

这里的答案说使用绝对路径会导致运行更大的Node应用程序时出现重大问题!

真正完整的解决方案

查找Node路径

which node

编辑 Cron 作业

crontab -e

将您的变更 Cron Job 设置为CD到目标文件夹,通过完整路径调用 Node Path 并运行脚本

*/2 * * * * cd /home/destination/path && /bin/node index.js

这将使您能够运行完整的NodeJS应用程序,而不会出现像使用绝对路径来访问 index.js 文件时遇到的所有错误。


1
感谢您提供正确的答案,我尝试了得票最高的解决方案,但我的脚本没有起作用,然后我尝试了其他解决方案,如lig node-cron,但是您的解决方案有效,而且简单易懂! - carmolim
1
这对我来说也是完美的答案,谢谢! - Smlok
这个对我也有效。谢谢,伙计。 - Rajan Twanabashu
这应该被标记为答案。谢谢伙计! - Jestin
这真的让我很烦恼。谢谢!还有一条提示给其他人。对我来说,困惑的是Ubuntu上的Cron作为root运行,即使你没有以此身份进行编辑。确保你的路径是从根目录绝对的,而不仅仅是从你的个人资料。 - isshakes
显示剩余3条评论

30

此外,只需在要执行的脚本顶部添加#!/usr/local/bin/node,然后它就会自动知道使用node来执行该脚本。确保该文件也具有可执行权限。


29
#!/usr/bin/env node比较有未来性,因为env会指向你安装的任何位置的node - Mauvis Ledford

13

您还可以在用户定时任务表的顶部指定二进制文件的路径,例如:

PATH=/bin:/usr/bin:/usr/local/bin

* * * * * cd your/path && node foo.js
* * * * * cd your/path && npm run bar

1
太完美了!这正是我想要的! - Alireza

8

在我的Linux Mint电脑上,给出的路径无法使用,所以我使用了以下方法来解决问题。

$ which node

$ /usr/bin/node 这对我有用。


6
这也适用于用户级别的cron作业。
 */2 * * * * cd /home/destination/path && $(which node) index.js

如果您正在使用像 NVM 这样的版本管理器,那么使用 $(which node) 就非常好。 - AFK

4

NVM用户:

请将以下脚本保存在任意路径下(比如:$HOME/bin)并确保可执行(chmod +x)。请将“username”替换为您的用户名:

#!/bin/bash
export NVM_DIR="/home/username/.nvm"   #replace "username" with your user name
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"  # This loads nvm

编辑cronjob:

crontab -e

插入/编辑您的工作:

0 0 * * * (. ~/bin/cronjob.env.sh; ~/bin/my-script-with-node-cmd.sh)

调用node命令(而不是一些shell脚本),像下面的作业一样,同样有效:

*/1 * * * * (. ~/bin/cronjob.env.sh; node ~/index.js)

PM2用户:

另一种方法是使用pm2,并使用--cron选项,该选项接受定时任务的cron表达式(需要用引号括起来):

pm2 start index.js --no-autorestart --cron "0 0 * * *"

--no-autorestart 是用于一次性脚本的(否则,每次完成后它都将重新启动)。


4
我不确定将脚本中的相对路径更改为绝对路径是否明智。(如果您的文件系统更改或您在另一个环境中部署会发生什么?)
你可以尝试将其包装在 shell 脚本中,在 crontab 执行中设置一些环境变量。(特别是 PATH 和 NODE_PATH 作为起点)
尝试我的建议,针对这个类似的问题:
https://dev59.com/pl8d5IYBdhLWcg3w41nz#27823675

0
如果您想保留 nvm 的功能,并允许您的代码获取更新的 node 版本而无需更改 cron job 信息,请将您的任务放入一个 shell 脚本中,该脚本首先设置nvm,切换到适当的node版本,然后运行实际的任务。这里是一个名为 invoicing 的项目示例,其中包括一个在其package.json中的cron脚本。

文件invoicing.sh:

#!/bin/bash
cd /home/produser/invoicing
export NVM_DIR="/home/produser/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
npm run cron

然后将此设置为您的cron作业列表中的命令:

0 16 1 * * produser /home/produser/invoicing/invoicing.sh

现在,如果您更改项目中的节点版本并使用正确的版本号更新您的.nvmrc,然后将新代码拉到服务器上,下次cron作业运行时它将使用指定的节点版本运行。请注意,您还必须确保服务器具有所需的节点版本。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接