快速修复
# 一键:crontab 顶部声明完整 PATH(最常用修复)
# 第一行:PATH=~/.nvm/versions/node/v20/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
按你的实际路径写;改完 crontab 文件 重载。
你会遇到什么
crontab 定时任务跑起来后报找不到命令:交互终端里 which node 明明有结果,cron 任务却只留一行 /bin/sh: 1: demo-node: not found。或者任务能跑但读不到环境变量(NVM_DIR、CONDA_PREFIX、自定义 export)。日志只有一行,没更多线索。
本文路径:快速修复(30 秒一段命令)→ 一步步排查(可跳读)→ 原理与变体(症状/原因/证据)。赶时间直接跳到「快速修复」。
为什么会这样
cron 执行任务的 shell 与我们交互终端的环境完全不同:
| 差异点 | 说明 |
|---|---|
| 不加载 shell 配置 | cron 用 /bin/sh 执行,~/.bashrc、~/.profile、/etc/profile 全不加载——nvm/conda/pyenv 的初始化全部缺失 |
| PATH 由 cron 守护进程决定 | 传统 SysV cron 默认 /usr/bin:/bin,不含自定义目录 |
| systemd 场景(实测) | systemd 以 cron -f -P 启动时 PATH 含 /usr/local/bin,真正中招的是 ~/.nvm/versions/.../bin、conda 环境目录这类"只在 .bashrc 里加"的路径和变量 |
| alias | cron 环境里 alias 不生效 |
cron 的执行环境与交互终端是两套环境:cron 用 /bin/sh 执行任务,不加载 ~/.bashrc/~/.profile//etc/profile——nvm/conda/pyenv 的初始化(只在 rc 里 export)全部缺失;
PATH 由 cron 守护进程决定(传统 SysV cron 默认 /usr/bin:/bin,systemd 启动的 cron 稍宽但同样不含「只在 .bashrc 里加的路径」)。
alias 在非交互 shell 里本来就不生效。
确定性推论:cron 里「命令找不到/环境变量空」≠ 系统坏了,是「该命令不在 cron 的 PATH 里」;
三条正路——脚本开头显式 export PATH=... 或写命令绝对路径(/usr/bin/python3)、把需要的初始化写进脚本本身(source ~/.bashrc 在 cron 里也可用但要看具体 shell)、或 cron 行里写 bash -lc 模拟登录环境(最接近终端,但引入终端环境的不确定性);
调试用 * * * * * cmd >> /tmp/cron.log 2>&1 看实际环境;
判断路径:手动能跑、cron 不能 = 环境差异,不是脚本逻辑。
一步步来
1. 先确认任务的环境 — 必做
临时把 printenv > /tmp/cron-env.txt 2>&1 放进任务,跑一次看 PATH 和变量——比猜快得多。或直接看 cron 守护进程环境:
tr '\0' '\n' < /proc/$(pgrep -x cron)/environ | grep PATH
2. 修复 A:crontab 顶部声明 PATH — 必做
PATH=... 放在 crontab 第一行,任务就能用相对命令名。
3. 修复 B:任务里用绝对路径 — 必做
~/.nvm/versions/node/v20/bin/node /path/script.js
不依赖 PATH,最稳。
4. 修复 C:任务内先加载环境 — 必做
. "$HOME/.bashrc" && mycmd
注意 .bashrc 通常有非交互守卫;更稳的是把需要的东西写进独立 env 文件,任务里 . /path/env.sh && mycmd。
5. 调试技巧 — 必做
任务输出重定向到日志(>> /tmp/job.log 2>&1);失败时第一行里的 xxx 就是要补路径/变量的那个命令。
怎么确认修好了
任务正常执行(实测输出形态):
crontab 声明 PATH 后 → 任务日志输出 NODE-OK <时间>(实测)
绝对路径版 → 同样正常执行(实测)其它环境的表现
| 环境 | 说明 |
|---|---|
| 传统 SysV cron | 默认 PATH=/usr/bin:/bin,顶部声明 PATH |
| systemd cron | PATH 含 /usr/local/bin(实测),nvm/conda 目录仍需显式声明 |
| nvm/conda/pyenv | 初始化在 .bashrc,cron 不加载 |
| alias | cron 里不生效 |
| 调试 | printenv 进任务,或 /proc/<cron pid>/environ |
症状
crontab 定时任务跑起来后报找不到命令 / 环境不对:
# 任务里调用 node(nvm 装的)、conda、或自定义脚本,日志只有一行:
/bin/sh: 1: demo-node: not found
特征:交互终端里命令明明能用(which node 有结果),但 cron 任务执行时 command not found; 或者任务能跑但读不到环境变量(NVM_DIR、CONDA_PREFIX、自定义 export); cron 日志里只有一行 /bin/sh: N: xxx: not found,没有更多线索; 常见于:nvm/conda/pyenv 装的工具、~/.bashrc 里 export 的变量、需要登录 shell 才有的环境。
原因
cron 执行任务的 shell 与我们交互终端的环境完全不同:
- cron 用
/bin/sh执行命令,不加载~/.bashrc、~/.profile、/etc/profile——nvm/conda/pyenv 的初始化(它们都写在~/.bashrc里)全部缺失; - 任务的 PATH 由 cron 守护进程决定:传统 SysV cron 默认
/usr/bin:/bin,不含/usr/local/bin,更不含 nvm/conda 的自定义目录; - 反常识实测(本机 Ubuntu 26.04):systemd 以
cron -f -P启动时,任务继承的是 systemd 的 PATH
(/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/snap/bin)——/usr/local/bin 其实可用, 真正中招的是 ~/.nvm/versions/.../bin、conda 环境目录这类"只在 .bashrc 里加"的路径和变量;
- 别名(alias)也一样:cron 环境里 alias 不生效。
解法
- 先确认任务的环境:临时把
printenv > /tmp/cron-env.txt 2>&1放进任务,跑一次看 PATH 和变量——
比猜快得多;或直接看 cron 守护进程环境:tr '\0' '\n' < /proc/$(pgrep -x cron)/environ | grep PATH。
- 修复 A:crontab 顶部声明 PATH(最常用):
PATH=~/.nvm/versions/node/v20/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 放在 crontab 第一行,任务就能用相对命令名。
- 修复 B:任务里用绝对路径:
~/.nvm/versions/node/v20/bin/node /path/script.js——不依赖 PATH,最稳。 - 修复 C:任务内先加载环境:
* * * * * . "$HOME/.bashrc" && mycmd(注意 .bashrc 通常有非交互守卫,
更稳的是把需要的东西写进一个独立 env 文件,任务里 . /path/env.sh && mycmd)。
- 调试技巧:cron 任务输出重定向到日志(
>> /tmp/job.log 2>&1),失败时第一行/bin/sh: N: xxx: not found
里的 xxx 就是要补路径/变量的那个命令;修好后重跑一次并确认日志出现正常输出。
验证证据
- 本地实测(2026-08-29,Ubuntu 26.04 LTS,systemd cron,任务输出重定向捕获):
- 环境基线:
cron -f -P(systemd cron.service)→ cron 进程 PATH 实测为
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/snap/bin;
- 模拟 nvm/conda:命令
demo-node只装在~/nvmbin/(不在上述 PATH); - 失败版:crontab 不声明 PATH,任务
* * * * * demo-node >> /tmp/cron-debug.log 2>&1→
下一次刻度后日志为 /bin/sh: 1: demo-node: not found(与 SO #21775749 同款现象);
- 修复 A:crontab 顶部
PATH=$HOME/nvmbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin→
任务正常执行,日志输出 NODE-OK <时间>;
- 修复 B:任务改为
~/nvmbin/demo-node绝对路径 → 同样正常执行; - 清理:测试 crontab 已删除、cron 已停止、临时文件已删除(宿主 root crontab 无残留)。
- 素材:SO #21775749《Command not found even crontab PATH is set》(老教程普遍只讲"cron 默认 PATH=/usr/bin:/bin",
本条目补上了 systemd 场景的实测修正)。
- 实测复现日志(2026-08-29)
适用工具 (1)
本问题方案已挂到下列工具的方案页——从工具页也能回到这里,双向可达。
cron · 外部工具来源与证据
素材来源:https://stackoverflow.com/questions/21775749/command-not-found-even-crontab-path-is-set
← 编码代理与终端 问题域 | 问题货架 | 遇到其它问题?去 问题空间 提交求助卡