刚把一台业务服务器从 CentOS 7 迁到 Rocky Linux 9顺手管了一批新人的权限。其间发现一个很有意思的现象很多人在 Linux 下折腾了大半年仍然搞不清su和sudo到底什么关系。被问得多了我觉得值得把这两个命令掰开揉碎讲清楚因为它们的区别不只是“一个要输 root 密码、一个输自己的密码”这么简单背后是两套完全不同的权限设计思路。这篇东西我不会写成命令大全而是按我实际排障的习惯把两个命令的定位、配置、以及几个高频报错的完整排查过程写出来。看完你至少能明白什么场景该用哪个、怎么给普通用户开权限、以及那个烦人的“鉴定令牌操作错误”到底怎么回事。1. 不要把 su 和 sudo 当成一回事1.1 两者解决的是不同层面的问题su的全称是 substitute user意思是切换用户。执行su root之后你当前这个 shell 会变成 root 的交互式 shell后续敲的每条命令都默认带着 root 身份直到你执行exit退出为止。它的特点是换人我从普通用户张三直接变成了 root 李四。sudo则完全不同。它的设计目标是允许某个普通用户以另一个身份默认是 root去执行某一条指定的命令。命令跑完权限就收回你的 shell 仍然是普通用户张三。它的特点是借权张三还是张三只是在执行这一条命令的瞬间系统借给他 root 的身份证。举个生活例子上来就好理解了。su相当于你把整个办公室的钥匙都借来了进门之后想干什么干什么甚至可以再配一把钥匙sudo则是你在门口刷一下脸保安放你进去拿一个指定文件出来之后门继续锁着你的权限还是原来的权限。这个本质差异造成了三个直接后果第一鉴权对象不同。su验证的是目标用户的密码也就是 root 的密码sudo验证的是当前用户自己的密码前提是这个用户已经出现在/etc/sudoers里。这意味着一个团队里如果所有人共用 root 密码一旦某个人离职或泄露密码整台机器的 root 访问权都得换而用sudo你可以只给某个人开放特定几条命令随时可以收回。第二审计能力不同。su切过去之后所有操作都变成 root 进程多数系统默认的日志配置很难追溯到“到底是哪个真人执行了这个 root 命令”。多人维护的服务器上这就是责任追溯的灾难。而sudo会把每次授权的命令、时间、用户都记录到/var/log/auth.log或/var/log/secure谁在什么时候执行过什么一目了然。第三授权粒度不同。su一给就是全部权限sudo可以精确到用户、主机、目标身份、具体命令。比如你可以配一个规则让某个用户只能重启 Nginx连重启 MySQL 的权力都没有。很多初学者会把sudo当成“用 root 的权限去跑命令”这句话只对了一半。准确的说法应该是sudo是系统根据配置好的规则临时赋予你执行某条命令的权限。规则外的东西即使你拿着 root 权限也跑不了。所以不要问“为什么我 sudo 了还是 Permission denied”先去看你 sudoers 里到底给了什么。1.2 什么时候我坚持用 sudo什么时候我认了用 su先说一个容易混淆的点sudo -i和sudo su -这类用法看起来最终都会给你一个 root shell但入口身份和日志记录方式还是有区别的。sudo -i是以 root 身份启动一个登录 shell适合临时需要一段交互式的 root 环境但又不打算长期占用 root 密码的场景。sudo su -则是先用 sudo 提权再调用 su 切换环境等于绕过了 root 密码验证直接进入 root 登录 shell。两者可用但不建议作为日常默认习惯因为这等于把 su 的“全权代理”又带回来了。我的选择标准大致是这样的一次性命令一律sudo。比如sudo systemctl restart nginx、sudo vim /etc/selinux/config用完即走不留交互 shell。连续多个维护操作比如要在/etc下改好几个配置、重启服务、看日志再一步步sudo就显得很累而且每条命令都走一遍审计记录反而把日志刷得很乱。这时候我倾向sudo -i或者直接su - root节省操作成本。多人管理的生产环境坚持sudo不给 root 密码。谁改了什么日志追得回来。这是底线。自动化脚本用sudo配合NOPASSWD白名单指定命令而不是把 root 密码写进脚本。脚本里明文存 root 密码是个定时炸弹。一句话记忆法日常顺手操作用 sudo成段维护作业用 su多人挨个上服务器必须 sudo。如果你还在用哪种之间犹豫优先 sudo权限给少了可以加给多了可不好收。1.3 普通用户到底能不能直接用 su这里要单独提醒一下在很多发行版上普通用户执行su root并输入正确密码后仍然会被拒绝提示su: 鉴定失败或类似的鉴权错误。原因不是密码不对而是 PAM 配置里限制了“只有某些组的成员才能 su 到 root”。典型的配置在/etc/pam.d/su里有一行auth required pam_wheel.so use_uid这行打开后只有wheel组的用户才能用 su 切换到 root。设计意图是防止持有 root 密码的用户无限自由使用必须同时属于受信任的组。所以如果你用 su 总是不明不白失败先检查自己是否在wheel组id groups如果不在加入即可sudo usermod -aG wheel yourname不过注意加入组之后需要重新登录终端才会生效。2. 配置权限前必须先理清的细节2.1 su 的几个参数以及它背后那套 PAM 流程很多人用su root和su - root的习惯很随意觉得无非多一个短横杠。其实这个短横杠决定了“你切换过去之后面对的是不是一个完整环境”。su root只切换用户的 UID/GID不重新加载登录环境。切换后PATH 还是原用户的可能找不到/sbin/ip等管理命令当前目录也不会自动切到/root。su - root完整模拟登录过程加载 root 的登录脚本、环境变量、PATH、当前目录也切到/root。所以如果你切到 root 后发现ip、systemctl这些命令执行不了大概率是用成了不带横杠的su root。我平时用 su 一律写su -除非有特别原因否则不加横杠的 su 只会带来一堆奇怪的环境变量问题。另外su的认证过程本身走的是 PAM。它会读取/etc/pam.d/su依次调用pam_authenticate等模块做密码验证、账户状态检查、资源限制设置。这也是为什么 root 密码即使正确如果账户被锁、密码过期、PAM 配置异常su一样会失败。排错的时候不要只怀疑密码要往 PAM 那一层的配置去想。一个细节su -会重新加载目标用户的环境但如果你期望的是“完全像重新登录一样”那么不仅 environment 会重置一些 PAM 会话模块也会重新初始化比如 umask、core dump 限制、可打开文件数等。所以遇到 su 进去之后 ulimit 跟预想的不一样不用大惊小怪这是 PAM 会话层在处理。2.2 sudoers 文件整个 sudo 系统的规则核心sudo的配置集中在/etc/sudoers以及/etc/sudoers.d/目录下的片段文件。它的基本语法是授权对象 主机(以什么身份) 命令比如xlous ALL(ALL:ALL) ALL意思是用户 xlous 可以在所有主机上以所有用户和所有组的身份执行所有命令。这是一条超级权限相当于完整 root。如果不希望给所有人那么大权力可以精确到命令xlous ALL(root) /usr/bin/systemctl restart nginx这样 xlous 只能用 sudo 执行systemctl restart nginx其他命令一律不行。注意命令要写绝对路径否则 sudo 会拒绝匹配防止 PATH 被恶意篡改。组授权用%开头%wheel ALL(ALL) ALL给命令集合起别名用Cmnd_AliasCmnd_Alias SERVICE /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx xlous ALL(root) SERVICE需要注意的坑太多了但最核心的一条不要直接拿 vim 编辑/etc/sudoers一定要用visudo。因为sudoers语法错误会导致整个 sudo 不可用而 visudo 在保存时会做语法校验。visudo也默认用vim作为编辑器所以搜索热词里的 sudo vim属于典型的误导——如果确实用 vim 打开了 sudoers 手动修改务必保持格式完全正确并且复制原文件备份否则坏了只能到物理控制台或单用户模式修复非常被动。2.3 经典场景sudo chown 配合容器权限问题很多人搜“sudo chown -r 1000:1000 ./data”这种命令多半是碰上了 Docker 容器的卷挂载权限问题。我简单还原一下你在宿主机上有一个数据目录./data容器内部进程以 UID 1000 的身份运行把这个目录挂载进去后容器进程想写文件却提示 Permission denied。原因通常是宿主机上这个目录的属主是 rootUID 0容器里的 UID 1000 用户没有写权限。解决办法之一就是sudo chown -R 1000:1000 ./data把属主改成 UID/GID 1000。-R是递归把目录下所有子文件全都改掉。这里我想提醒三点第一chown -R是非常重的操作执行前先确认目录范围没错尤其是别在挂载点根目录上随手递归。目录挂错了递归下去会把一堆系统文件的属主全打乱通常只能重装。第二如果只想让容器内用户可写但又不想改动宿主机目录的所有权更精细的做法是用 ACLsudo setfacl -R -m u:1000:rwX ./data这样只给 UID 1000 的用户加了一条访问控制条目比直接 chown 更温和也不会影响其他用户对目录的访问。第三遇到所有权错乱之前先确认容器到底以哪个 UID 在跑。很多镜像里面是 root 用户运行的生成的目录文件属主会是 root而宿主上你日常登录的用户多半不是 root于是你又会想为什么目录删不掉这时候sudo ls -ln ./data看数值 UID 最直观。不要凭感觉先看数值。3. 实操从普通用户到 root 权限的完整打通路径3.1 给普通用户开通 sudo 权限的两种标准姿势假设现在有个用户叫xlous要把它纳入 sudo 管理。主流发行版有两种模式方式一加入系统预定义的 sudo 组Debian/Ubuntu 系列sudo usermod -aG sudo xlousRHEL/CentOS/Rocky 系列sudo usermod -aG wheel xlous这条命令的作用是把用户追加到支持 sudo 的组里。前提是/etc/sudoers里已经默认包含了对应组的授权而多数发行版默认就是这样。-aG里的-a千万别漏。-a是“追加”如果没有-ausermod -G newgroup会把用户从原有附属组里全部踢出去很可能导致用户瞬间失去 docker 等组的访问权限还不好排查因为报错非常奇怪。方式二单独给用户写一条 sudoers 规则我推荐为每个有特殊诉求的用户单独建片段文件不要全堆在主文件里sudo visudo -f /etc/sudoers.d/xlous文件里写xlous ALL(ALL:ALL) ALL保存退出。visudo -f会检查这个文件的语法检查通过之后sudo才会加载它。如果你写坏了visudo 会拒绝保存相当于是最后一道防线。两种方式如何选如果只是“让这个用户能 sudo 任意命令”用组方式最简单系统升级也不容易出问题。如果是“这个用户只能运行指定命令”就必选方式二单独写规则文件细粒度控制。验证是否生效不要只靠猜。重新登录一次然后执行sudo -l这会列出当前用户在 sudo 下能执行的所有命令。执行sudo whoami输出root说明权限已经生效。3.2 一个容易忽略的点重登与密码缓存用户刚加入 sudo 组时旧会话里很可能并不生效。因为用户组的读取是在登录时完成的当前 shell 的用户组集合不会动态刷新。遇到“明明加了组sudo 还是说不在 sudoers 里”先让他退出重新登录或者执行newgrp sudo刷新会话的组身份再试。还有一个跟排障相关的细节sudo 默认会有大约 5 分钟的时间戳缓存。这个缓存是按终端tty区分的你在这台机器上 sudo 输过一次密码5 分钟内在同一个终端再次 sudo 不需要重复输入但换个终端就得重新输。用sudo -k可以主动清掉缓存。这个机制在自动化脚本里经常咬人——脚本在一个终端里循环执行 sudo第一次输完密码后后续可以跑但换到另一个终端就莫名卡住。3.3 “设置 root 密码时 su: 鉴定令牌操作错误”的完整排查过程这个报错是我在后台私信里被问得最频繁的一条。中文系统环境下执行su时看到su: 鉴定令牌操作错误英文原生提示是su: Authentication token manipulation error或su: Authentication failure。“鉴定令牌”说的就是密码验证的令牌。看到这个别慌按顺序查这几样第一步确认密码真的输入正确很多人第一遍设好 root 密码转头用 su 时键盘布局或大小写没对上就提示这个错。可以先在另一个终端用su -反复确认一次确认不是手滑。su输密码时终端不显示任何字符这是正常的不要以为键盘失灵。第二步确认 root 账户没有处于锁定状态Ubuntu 及一些衍生版默认不启用 root 账户root 密码未设置等价于锁定状态。可以直接看sudo passwd -S root输出里出现L或Locked字样说明 root 账户被锁。这时候 su 到 root 自然会失败。解决办法是重新设置一个 root 密码sudo passwd root如果只是想临时解锁也可以sudo passwd -u root第三步检查 /etc/shadow 里 root 的密码字段sudo awk -F: /^root/{print $2} /etc/shadow正常情况你会看到一长串以$6$、$y$或类似开头的 hash 字符串。如果看到!开头或*说明密码字段被锁定或没有密码su基本不可能通过。这个排查能区分“密码错”和“账户锁定”两个完全不同的原因。第四步看看是不是 PAM 或失败锁定模块在捣乱有些系统装了pam_faillock连续输错密码会导致账户临时锁定。检查一下sudo faillock --user root如果显示多次失败记录先复位sudo faillock --user root --reset另外/etc/pam.d/su里的配置也可能有问题。最常见的就是前面说的pam_wheel限制也有可能是某些安全类模块把 su 的认证流程挡了。实在不行在维护时机允许时可以用sudo -i代替su -进入 root 环境这样绕开的是 sus 的验证层但并没有破坏任何权限体系只是换了一条入口。第五步不要忽视密码过期策略如果系统实施了密码策略root 密码过期也会造成类似问题。执行sudo passwd -S root输出里的日期如果显示过期直接再设置一次新密码就好顺带还能更新过期时间。排查到这一步su: 鉴定令牌操作错误的事基本都可以定位。绝大多数人最后回头一看要么是 root 账户没启用要么是密码抄错了。4. 常见问题速查表与我的避坑技巧4.1 高频报错速查报错或现象可能原因处理方向su: 鉴定令牌操作错误密码错误、root锁定、PAM限制、faillock锁定确认密码检查passwd -S root检查 shadow重置 faillockxxx is not in the sudoers file. This incident will be reported.用户不在 sudoers 白名单中用 root 或已有 sudo 用户执行visudo添加授权用户加入 sudo 组后仍然报 not in sudoers会话没有重新加载组身份退出重登或执行newgrp sudosudo: 找不到命令/command not foundPATH 里没有目标命令路径使用绝对路径如/usr/sbin/nginx确认/etc/sudoers的 secure_pathsudo: no tty present and no askpass program specified非交互环境执行 sudo脚本中给用户配置NOPASSWD白名单或避免在无终端场景下使用 sudosudo: /etc/sudoers is world writablesudoers 权限被误改以 root 执行chmod 440 /etc/sudoers执行sudo chown -r后服务还是没写入权限UID 不对或容器内用户 UID 并非 1000用sudo ls -ln看数值容器启动参数中确认 UID修改 sudoers 后所有 sudo 全部失效语法错误或权限错误物理控制台/root 登录修复恢复备份运行visudo -c4.2 编辑 sudoers 文件前一定先备份并验证处理 sudoers 文件时我习惯先原地复制一份备份sudo cp /etc/sudoers /etc/sudoers.bak.$(date %F)然后去改改完先visudo -c验证语法。如果发现语法错误且 sudo 已经不可用root 登录后用备份文件原地恢复cp /etc/sudoers.bak.20250620 /etc/sudoers chmod 440 /etc/sudoerschmod 440是 sudoers 的标准权限。sudoers 如果变成644甚至666sudo 会直接拒绝加载这是文件完整性检查的一部分。很多人不知道这一点手滑 chmod 一次之后所有 sudo 命令都躺下了。4.3 关于“用户不在 sudoers”的细节处理“xlous 未出现在 sudoer 文件中”这类提示在很多截图里看过了。语法上正确的叫法应该是/etc/sudoers而不是sudoer但实际报错文案在不同发行版有简写不必纠结。处理时记住一个优先级如果你能登录 root直接visudo如果你连 root 都进不去但还有其他 sudo 用户用那个用户去sudo visudo如果全机器只有 xlous 一个账户且它没有 sudo 权限那只能通过启动时的单用户模式或物理控制台或者从 Live 环境挂载系统盘修改没有别的“按几个键就绕过系统权限”的捷径。越到这种时候越能体现配置前备份的重要性。4.4 我在日常使用中的一些习惯几个用了多年、踩过坑后沉淀下来的习惯供你参考第一日常命令能用 sudo 就不要 su。特别是那些带操作词的系统管理命令比如 systemctl、useradd 等。一是日志清晰二是万一命令敲错sudo 的权限边界至少能挡一下不至于整个 shell 都是 root 身份一错再错。比如我在执行rm这种高危命令时宁可sudo rm ...也不 su 进 root 再删因为一旦把rm -rf的 target 写错root shell 里没有防护灾难是瞬时的。第二sudo -i是临时管理维护的好工具。它需要你当前用户具备 sudo 权限然后以 root 身份起一个完整登录环境。跟su -相比它不要求你知道 root 密码也受 sudoers 规则约束比较适合日常维护。第三不要迷信 NOPASSWD。自动化脚本里为了免交互设置 NOPASSWD我能理解但请务必把允许的命令写到最小白名单。写NOPASSWD: ALL等于把这台服务器完全托付给该用户的任何操作而且不需要密码风险等同把 root 密码贴在显示器上。我见过因为NOPASSWD: ALL导致误删文件后又无法从审计日志追责的情况非常难受。第四定期sudo -l审视现有权限。每过一段时间把所有人的 sudo 权限列一遍看到不合理的ALL及时收缩。这是权限治理成本最低的一种方式没什么门槛但很多人懒得做。4.5 最后再分享一个和 Termux 这类环境相关的小场景搜索热词里有人问“termux 如何从 su 模式退出”。这种 Android 终端环境下的 su本质和 Linux 的 su 是一样的逻辑进入 root 环境后输入exit就能退回普通用户。如果你发现自己处于#提示符下说明已经是 root 身份的 shell输入exit退到$提示符意味着恢复普通用户身份这是最直接的判断依据。这里顺便强调一个概念exit退出的不是“root 身份”而是“当前这个登录 shell 会话”。如果用了su -那个登录 shell 退出后才会回到上一个 shell 的主人。Linux 的权限管理从来不是一句“用 root 跑就完事”能概括的su 和 sudo 正是这套管理体系里最常用也最容易被误用的两个入口。把它们的区别和各自的坑理解透遇到权限类报错时你会少走很多弯路。