You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

直接运行Node.js文件正常但Cron执行失败,出现ERR_REQUIRE_ESM错误求助

直接运行Node.js文件正常但Cron执行失败,出现ERR_REQUIRE_ESM错误求助

这种情况我之前排查过好多次,核心问题基本都出在Cron的执行环境和你日常登录shell的环境不一致上,咱们一步步来拆解问题和尝试解决:

1. 先解决最常见的「环境/路径差异」问题

你在终端手动运行脚本时,用的是当前用户的完整环境变量(比如NODE_PATH、PATH里的Node版本路径),而且工作目录是项目根目录;但Cron的执行环境非常精简,默认工作目录是/,环境变量只有系统最基础的配置,这会导致两个关键问题:

  • Node可能找不到正确的模块解析路径
  • 甚至可能用的不是你日常使用的Node版本(虽然日志里显示是v20.11.0,但还是要确认)

快速尝试修复:在Cron命令里先切换工作目录

把你的Cron任务改成先进入项目目录再执行脚本,这一步往往能解决80%的路径相关问题:

00 01 * * * cd /home/adrian/nfp-repo/login && node upd_ATC_ALC_daily_from_server_file.js >> /tmp/crlog.log 2>&1 | logger -t mycmd

进阶确认:打印Cron的环境信息

如果切换目录后还是不行,可以先在Cron里打印环境变量和Node版本,对比和你终端的差异:

00 01 * * * echo "=== Cron Environment ===" >> /tmp/crlog.log && node -v >> /tmp/crlog.log && echo $PATH >> /tmp/crlog.log && cd /home/adrian/nfp-repo/login && node upd_ATC_ALC_daily_from_server_file.js >> /tmp/crlog.log 2>&1 | logger -t mycmd

然后对比终端里运行node -v和echo $PATH的结果,要是发现Node版本不一样,就用终端里which node得到的完整路径替换Cron里的node,比如:

00 01 * * * cd /home/adrian/nfp-repo/login && /home/adrian/.nvm/versions/node/v20.11.0/bin/node upd_ATC_ALC_daily_from_server_file.js >> /tmp/crlog.log 2>&1 | logger -t mycmd

2. 针对日志里的「ES模块兼容」报错

日志明确说@exodus/bytes是ES模块,但html-encoding-sniffer用CommonJS的require()去加载它,Node.js v14+就不允许这种跨模块加载了。那为什么手动运行没问题?

  • 大概率是你手动运行时,项目根目录的package.json里有"type": "module"配置,让Node自动把整个项目当作ES模块处理,兼容了这种加载方式;但Cron默认在/目录执行,找不到项目的package.json,所以用了默认的CommonJS规则,就触发了报错。
  • 解决这个的核心还是让Cron在项目目录下执行脚本,这样Node能读到package.json的配置,和你手动运行时的规则一致。

3. 极端情况的临时修复

如果以上方法都不行,也可以尝试修改依赖的加载方式(不推荐,属于临时hack,下次npm install会被覆盖):
找到/home/adrian/nfp-repo/login/node_modules/html-encoding-sniffer/lib/html-encoding-sniffer.js里的报错行,把:

const { getBOMEncoding, labelToName } = require("@exodus/bytes/encoding-lite.js");

改成动态import()的方式:

let getBOMEncoding, labelToName;
(async () => {
  const module = await import("@exodus/bytes/encoding-lite.js");
  getBOMEncoding = module.getBOMEncoding;
  labelToName = module.labelToName;
  // 后续依赖这两个方法的逻辑也要放在async函数里,或者用.then()处理
})();

备注:内容来源于stack exchange,提问作者Adrian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:28:03