问题出现得很突然,日志倒是留得挺全。Ubuntu 20.04 上运维账号用 sudo 跑一个部署脚本,脚本里调 kubectl 报 command not found,直接执行却正常,PATH 在工作台看上去完全一样。
刚开始盯着「sudo 默认 env_reset,普通用户导出的 PATH 和自定义变量都被清掉」,折腾了半个多小时,排掉了。
这类报错背后常见的原因有几处,逐个排除就行。sudoers 里的 secure_path 会覆盖调用者传入的 PATH,只保留系统目录。另一种情况是脚本里没有显式写命令的绝对路径,依赖环境变量找可执行文件。
不容易想到的是,命令装在 /usr/local/bin 之外的自定义目录,secure_path 里没有它。
先确认 sudo 下的实际 PATH
sudo sh -c 'echo $PATH' && sudo -l | grep -i secure_path
然后用绝对路径验证命令是否存在
sudo which kubectl || sudo ls -l /opt/k8s/bin/kubectl
随后在脚本里统一用绝对路径或者显式导出 PATH
sed -i '2i export PATH=/opt/k8s/bin:$PATH' /opt/deploy.sh
需要时按最小范围放开环境变量
echo 'Defaults env_keep += "PATH"' > /etc/sudoers.d/env-path && visudo -c
怎么算真的好了,看的是同一批现象。sudo 执行脚本时 echo $PATH 已包含命令所在目录,脚本各步骤返回码为零,日志里不再出现 command not found。
补一句。把 PATH 整个放行等于让用户决定 root 执行哪个同名命令,属于提权风险;优先改脚本用绝对路径,别图省事改 secure_path。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。