核心是用/etc/sudoers做白名单授权,通过visudo精确配置绝对路径命令、注意规则顺序、环境重置及权限校验,避免all误用和配置失效。

怎么让普通用户只能执行特定命令(比如重启服务)
核心就是用 /etc/sudoers 做白名单式授权,不是“开权限”,而是“列准许”。直接给 ALL 是最常见错误起点。
- 用
visudo编辑,别用vim /etc/sudoers—— 语法错一个字符,sudo可能全挂,连root都救不回来 - 写法示例:
alice ALL=(root) /usr/bin/systemctl restart nginx,注意路径必须绝对且精确(systemctl不在secure_path里就失败) - 如果要允许多个命令,用逗号分隔:
/usr/bin/systemctl, /bin/journalctl;禁止某条加!前缀,如!/bin/rm - 别漏掉
sudoers默认启用的env_reset:环境变量会被重置,所以脚本里依赖$PATH或自定义变量时会出乎意料地失败
为什么加了 NOPASSWD 还要输密码
不是配置没生效,大概率是规则顺序或匹配逻辑被覆盖了。sudoers 按从上到下匹配,第一条命中就停止,后面的同用户规则无效。
- 检查是否被更早的规则拦截,比如
%sudo ALL=(ALL:ALL) ALL在你自定义行上面,那你的NOPASSWD就压根没机会触发 -
NOPASSWD必须紧贴命令前,格式是:bob ALL=(root) NOPASSWD: /bin/ls, !/bin/rm;写成NOPASSWD:ALL是错的,ALL不是关键字,是通配符,需加引号或明确路径 - 确认用户确实属于目标组(如
%webadmin),用groups命令看,改完组别要重新登录才生效
/etc/sudoers.d/ 目录到底该怎么用
这是官方推荐的模块化方式,但很多人只建文件,忘了权限和命名规则,结果配置根本不加载。
- 文件名不能含
.或以~结尾,否则被忽略(例如web.conf或db.bak都无效) - 权限必须是
0440:sudo chmod 0440 /etc/sudoers.d/db-admin,否则 sudo 直接拒绝读取 - 确保主配置末尾有这行:
#includedir /etc/sudoers.d(默认 Ubuntu/CentOS 都有,但某些精简镜像可能删了) - 调试时用
sudo -l -U username查看该用户实际生效的规则,它会显示从哪个文件加载的哪条规则
sudo 失效了怎么办(比如改坏 sudoers 后连 root 都进不去)
别慌,这不是系统崩溃,只是权限策略卡死。关键在于绕过 sudo 本身去修复。
- 首选
pkexec visudo:只要桌面环境正常、polkit 配置没崩,它能以 root 身份调起编辑器 - 进 recovery mode 或 grub 单用户模式,挂载根分区后直接
mount -o remount,rw /,再visudo - 切忌用
chmod 777 /etc/sudoers救急——sudo 会因权限太宽松直接拒绝工作,报错:sudo: /etc/sudoers is mode 0777, should be 0440 - 改完务必运行
sudo -v测试是否恢复,再用sudo -l确认规则正确加载
真正难的从来不是写对一行配置,而是理解 sudo 的匹配优先级、路径锁定机制和环境隔离逻辑。哪怕只授权一个命令,也要把它当成最小攻击面来设计——多打一次字,少修一次故障。










