ubuntu crontab 定时执行 node 程序

2024-07-06 · 858 chars · 5 min read

之前一直没有用过 crontab,最近想要定时通过 rclone 备份一些文件,没想到踩到这么多坑:

  • 默认情况下没有开日志
  • crontab 里的 shell 是 sh,环境变量不一样
  • 时区问题,这个在 server 版的 ubuntu 上很容易遗漏
  • 命令执行错误会发邮件,然而一般系统是没有配置邮件的,日志会显示 (CRON) info (No MTA installed, discarding output)

下面我把弯路捋直了,直接讲讲我现在的用法。另外,文后的参考链接挺有用的,建议看看。

安装#

先来安装 crontab 服务

sudo apt install cron

设置开机启动

sudo systemctl enable cron

一些其他命令

sudo systemctl restart crond.service # 重启服务
sudo systemctl status crond.service  # 查看服务状态

开启日志#

默认情况下,crontab 的日志没有开启,执行

sudo vim /etc/rsyslog.d/50-default.conf

找到 cron.*,把前面的注视 # 去掉,保存

#  Default rules for rsyslog.
#
#                       For more information see rsyslog.conf(5) and /etc/rsyslog.conf

#
# First some standard log files.  Log by facility.
#
auth,authpriv.*                 /var/log/auth.log
*.*;auth,authpriv.none          -/var/log/syslog
cron.*                          /var/log/cron.log
#daemon.*                       -/var/log/daemon.log
kern.*                          -/var/log/kern.log

重启日志,重启 cron 服务

sudo systemctl restart rsyslog
sudo systemctl restart cron

之后就可以查看 cron 日志了

tail -f /var/log/cron.log

确认系统时区#

输入 timedatectl 命令查看:

               Local time: Sat 2024-07-06 20:10:25 CST
           Universal time: Sat 2024-07-06 12:10:25 UTC
                 RTC time: Sat 2024-07-06 12:10:24
                Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

如果你的时区不是 Asia/Shanghai 的话,执行 sudo timedatectl set-timezone Asia/Shanghai 设置一下。

非东八区可以执行 timedatectl list-timezones 命令找找。

解决 node 执行问题#

相信大多数前端和我一样,不会直接安装 node,而是使用了类似 nvm 的版本管理工具。

这就带来一个问题,nvm 切换 node 版本的时候会修改环境变量,执行 echo $PATH 查看:

/home/keenwon/.nvm/versions/node/v16.20.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

但是 crontab 的环境变量是不同的,所以直接用 node 命令 * * * * * node /path/index.js 会报错:

/bin/sh: 1: node: not found

我的解决办法是把 Nodejs 打包为一个可执行文件(Node.js SEA),可以查看这篇文章

配置定时任务#

最后,执行 crontab -e 即可为当前用户配置定时任务了,建议这么写

0 6 * * * /usr/bin/zsh -c "<你的 SEA 文件路径>" >/dev/null 2>&1

/usr/bin/zsh 可以换成你常用的 shell,避免麻烦。

>/dev/null 2>&1 是为了解决「邮件」问题,说明下:

  • /dev/null 是空设备文件,>/dev/null 的意思就是「什么都不输出」
  • 1 表示 stdout 标准输出
  • 2 表示 stderr 标准错误
  • & 表示「等同于」的意思
  • 2>&1 表示 2 的输出重定向等同于 1(1 就是 >/dev/null,就是什么都不输出)

所以 >/dev/null 2>&1 的意思就是「什么都不输出」,也就不会发邮件了。

最后#

文章写出来就这么多,但是第一次使用,每一步都是坑,说多了都是泪...

crontab 感觉比较适合简单用,如果要执行很多复杂任务,推荐看看「青龙面板」,我在 docker 里安装试了下,功能挺强大的。但 docker 是一个隔离的环境,不太符合我的需求,还是写点 node 代码比较简单。

参考#

赞赏

微信