Ubuntu 22.04 上写了个部署脚本,sudo 执行时里面调 java 报 command not found,手动跑没事,sudo -l 能看到 NOPASSWD,sudo env 里 PATH 只剩 /usr/bin:/bin。

一开始怀疑是「java 装在 /usr/local/jdk/bin,不在 secure_path 列表里」,查了一圈,方向不对。

把日志和配置对完,能解释这个现象的基本就这几处。sudo 默认 env_reset,把当前 shell 的 PATH 重置成默认值。另一种情况是sudoers 里的 secure_path 写死了,脚本里 export 的 PATH 被覆盖。

另外,脚本用 sh 执行,shebang 和环境变量都没继承下来。

先确认 sudo 下的环境

sudo env | grep -E 'PATH|JAVA_HOME'

然后查看 secure_path 的设置

sudo grep -rn 'secure_path' /etc/sudoers /etc/sudoers.d/

接着在 sudoers 里补上安装路径

echo 'Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/jdk/bin"' > /etc/sudoers.d/path && visudo -c

脚本里显式声明解释器和路径

sudo -E env PATH=/usr/local/jdk/bin:$PATH /bin/bash deploy.sh

白天有业务在跑,能验证的部分都压到了晚上做。

当时还开着另一个排查窗口,两边日志对照着看才定位到。

同一份数据我导出了两份,一份留底,一份拿来试。

改完先别撤,确认这几项。sudo 执行部署脚本能找到 java,java -version 输出正常,脚本退出码为 0。

这里还有个坑。改 sudoers 必须用 visudo 校验,写坏了会把 sudo 一起锁死;临时 sudo -E 能保环境,但脚本里写绝对路径更可靠。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189