欢迎光临
我们一直在努力

用户权限 01|su、sudo、sudo su、sudo -i 到底差在哪?先花两分钟搞懂 root 和普通用户

我有一次跟着一篇教程装软件,第一行就是 su root。

敲下去,输密码,报 鉴定失败。我以为记错了,又输了两遍,还是失败。换键盘布局、重启、甚至怀疑自己装系统时设的密码有问题——折腾了四十分钟。

最后才知道:Ubuntu 上的 root 账号默认是锁着的,根本没有密码可以输。 我在那儿拼命回忆的那个「root 密码」,从装完系统那天起就不存在。

这篇先把 root 和普通用户的关系讲清,再把 su、sudo 这一串长得差不多的命令摆在一起对照。看完你就知道:大部分教程让你敲的那条,其实不是最好的做法。

〇、先花两分钟:root 和普通用户是什么关系

登录一台 Linux,你其实是在「以某个用户的名义」操作。

你现在的名字,一行命令就能看到:

$ whoami
rainbow

你现在的身份编号,也是一行:

$ id
uid=1000(rainbow) gid=1000(rainbow) groups=1000(rainbow),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),111(lpadmin),114(lxd)

怎么读(这份输出后面还会反复用到,先花一分钟记住三件事):

片段含义
uid=1000(rainbow) 你的用户编号是 1000,名字是 rainbow
gid=1000(rainbow) 你的主组编号也是 1000
groups=… 你还属于哪些附加组(关键在下面)

Linux 里每个账号都有一个编号,叫 UID。有两个编号是特殊的:

UID是谁
0 root——系统里的最高权限账号
1~999 系统账号(Nginx、MySQL 这类服务专用,一般不允许登录)
1000 起 普通用户——你自己

打个比方:root 是大楼的管理员,能进任何一个房间、能换锁、能拉电闸;普通用户是有自己房间钥匙的住户,只能进自己那间。你日常干活用住户钥匙就够了,只有真的要动线路、动承重墙(装软件、改系统配置、看别人的文件)时,才需要请管理员来一下。

su 和 sudo 这两族命令,解决的就是「怎么把管理员请过来」的问题——只不过两族人的思路完全不同:

  • su = 换人:直接变成 root,之后敲的所有命令都是 root 在执行

  • sudo = 代跑:不动你的身份,只让 root 帮你跑这一条命令,跑完就还回去

先记住这个区别,下面所有的混乱都从这里来。

一、五条命令摆一起:各自要谁的密码

命令长得像,其实分成两族。最直接的区分办法是看它问你要谁的密码:

命令要谁的密码执行完你变成谁
su root 的密码 root
su – root 的密码 root(完整登录环境)
sudo 命令 你自己的密码 还是你自己,只那一条命令以 root 跑
sudo -i 你自己的密码 root(登录式)
sudo su 你自己的密码 root

看这张表最后三行——只要前面带 sudo,问的就是你自己的密码。 这是新手最容易搞混的地方:教程里让你敲 sudo su,你却在拼命想 root 密码,永远敲不进去。

那 su 和 sudo su 结果都是变成 root,为什么还要有后一种?因为前一种在 Ubuntu 上第一步就卡死。

二、su 为什么在你的机器上多半走不通

先查一下 root 账号的状态。注意这条命令要看密码哈希,所以得带 sudo——普通用户跑不了:

$ passwd -S root
passwd:您不能查看或更改 root 的密码信息。

换个路子,直接看密码文件。/etc/shadow 只有 root 能读,第 2 段就是密码状态:

$ sudo awk -F: '$1=="root"{print $1, substr($2,1,3)}' /etc/shadow
root $y$

怎么读:第 2 段的开头几个字符决定一切。

开头含义
! 或 * 锁定 / 没有可用密码——su 永远进不去
$y$ / $6$ / $1$ 已设密码($y$=yescrypt、$6$=SHA-512、$1$=MD5)——只要密码对,su 就能进

Ubuntu 桌面版安装时根本不问你 root 密码,官方文档的说法是给 root 分配了一个「不匹配任何可能值的哈希」——直白讲就是锁着。所以下面这一幕在默认机器上是必然会发生的:

$ su root
密码:
su: 鉴定失败

但别急着下结论。 我这台机器上实测第 2 段是 $y$j9T$…(yescrypt),说明它设过 root 密码——这不是装完系统就有的状态。所以如果你在自己机器上看到的是 $y$ 或 $6$,那 su root 失败只意味着一件事:密码敲错了,和「账号被锁」完全是两码事。

想确认自己属于哪种,两条命令二选一:

$ sudo passwd -S root            # 第二位:L=锁定,P=有密码,NP=无密码
$ sudo grep ^root: /etc/shadow   # 第 2 段:! / * = 锁定,$y$ / $6$ = 有密码

(如果你查出来的是 L,下一步通常就是「那我 sudo passwd root 设一个不就行了」——能设,但多数情况下不该设,理由写在第七节的坑 2 里。)

正确的替代动作是这一条:

$ sudo -i

输你自己的密码,回车,提示符变成 root@…#,你就变成 root 了。

三、sudo 到底做了什么

sudo 的全称是 "superuser do"(以超级用户身份做)。它做三件事:

  • 检查你有没有资格提权(看你在不在 sudo 组里);

  • 问你要你自己的密码;

  • 以 root 身份跑完你给的那一条命令,然后立刻归还权限。

  • 它凭什么判断你有资格? 回到第〇节那份 id 输出里的 groups:

    groups=1000(rainbow),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),111(lpadmin),114(lxd)
          └──── 你自己 ────┘ └adm┘ └cdrom┘ └─sudo─┘ …

    关键是 27(sudo) 这一项。

    你之所以能敲 sudo,就是因为你在这个组里(Ubuntu 装系统时,会把第一个用户自动加进 sudo 组)。

    顺带记住一个跨发行版的坑:RHEL / CentOS / Rocky 系里,这个组叫 wheel,不叫 sudo。 同样一条「把自己加进提权组」的教程,在 Ubuntu 上写 sudo,在 RHEL 上要写 wheel,抄错就是一个多小时。

    看自己被允许做什么:

    $ sudo -l
    用户 rainbow 可以在 rainbow-VMware-Virtual-Platform 上运行以下命令:
      (ALL : ALL) ALL

    怎么读:这一行要拆成三段看——「在哪台机器上 : 以谁的身份 : 能跑哪些命令」。

    (ALL : ALL) ALL 是三段全开:任何主机、任何身份、任何命令。

    桌面机上这样很方便,生产服务器上这样很危险——等于给了一把万能钥匙。真要做安全配置,就得动 /etc/sudoers,那部分放在本专栏的 C4 里讲。

    最后记住两条实用细节:

    • sudo 有一次 15 分钟的免密窗口:刚输完密码,短时间内再敲 sudo 不会再问;

    • 敲 sudo -k 可以立刻作废这个窗口(公共机器上走人前顺手敲一下)。

    最后一条,也是 sudo 比 su 更值得用的真正原因:它把每件事都记下来了。

    $ sudo grep -a sudo /var/log/auth.log | tail -3
    … sudo: pam_unix(sudo:session): session opened for user root(uid=0) by rainbow(uid=1000)
    … sudo: rainbow : TTY=/dev/pts/0 ; PWD=/home/rainbow/桌面 ; USER=root ; COMMAND=/usr/bin/sh -c …
    … sudo: pam_unix(sudo:session): session closed for user root

    怎么读:一行里能看出谁(by rainbow(uid=1000))、在哪台终端(TTY=/dev/pts/0)、在哪个目录(PWD=)、以谁的身份(USER=root)、跑了什么(COMMAND=)。

    su 按设计就是「换个人」,日志里只留一句「有人变成 root 了」,之后干了什么一概查不到——当一台机器不止一个人在用,「能不能追责」比「方不方便」重要得多。

    四、真机对照:sudo 之后,环境变没变

    这一节是本文最有用的一段——很多人踩的坑不在「能不能提权」,而在「提权之后环境变了」。

    把同一个问题分别问给「普通用户」和「sudo」:

    $ echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
    ​
    $ sudo printenv PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

    怎么读:把两条逐段对齐看——

    段你的 PATHsudo 下的 PATH
    /usr/local/sbin ✔ ✔
    /usr/local/bin ✔ ✔
    /usr/sbin ✔ ✔
    /usr/bin ✔ ✔
    /sbin ✔ ✔
    /bin ✔ ✔
    /usr/games ✔ ✘ 没了
    /usr/local/games ✔ ✘ 没了
    /snap/bin ✔(出现两次) ✔(一次)

    sudo 把 PATH 整个换掉了,不是往后追加。

    这不是随机的,是 /etc/sudoers 里一行配置写死的:

    $ sudo grep -n secure_path /etc/sudoers
    11:Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"

    怎么读:secure_path 的意思是——为了安全,sudo 不走你的 PATH,只走我指定的这条。防的是「你在自己目录里放个假 ls,然后忽悠 root 去执行」。

    代价就是:你自己装的、放在 /usr/local/games 或某些自定义路径下的命令,sudo 之后会突然「找不到」。

    (这正好是《报错排查 06》里第 3 种成因的现实版本。当时我们只知道「sudo 会重置 PATH」,现在你看到了它是在哪一行、怎么重置的。)

    $ cat /etc/environment
    PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"

    怎么读:这才是你那条 PATH 的「源头」——登录时由系统读进来。对比 sudoers 那行,多的正好是 /usr/games、/usr/local/games。两份配置、两套 PATH,这就是差异的全部来源。

    再补一刀:sudo 换掉的不只是 PATH,还有 HOME——但不换当前目录:

    $ pwd
    /home/rainbow/桌面
    ​
    $ sudo sh -c 'echo HOME=$HOME; echo pwd=$(pwd)'
    HOME=/root
    pwd=/home/rainbow/桌面

    怎么读:HOME 已经变成 /root,可 pwd 还停在 /home/rainbow/桌面。

    两条合起来就说明了 sudo 的本质——它不是「换人」,是「代跑」:只把几个环境变量(PATH、HOME)按 root 的配置重置一遍,进程所在的目录原封不动。

    所以有个经典事故:你 cd 到自己的项目目录,接着 sudo 某命令——命令是以 root 跑的,但落在你原来的目录里,不是 /root。反过来同样坑:sudo 之后 ~ 指的是 /root,sudo echo x > ~/a.txt 写的是 /root/a.txt 而不是你的家目录。这就是下一节坑 4 的另一个变体。

    五、su 和 su -:差在那个减号

    如果你哪天在一台有 root 密码的机器(比如 RHEL 系、或者你手动给 root 设过密码)上敲 su,会立刻遇到第二个坑:su 和 su – 不一样,差的不是一点点。

    su           → 换身份,但保留你当前的大部分环境
    su –         → 换身份 + 完整走一遍 root 的登录流程(等价于 su -l / su –login)

    具体差在哪,敲两条命令就现形了:

    对比项su 之后su – 之后
    pwd(在哪个目录) 还停在你原来的目录 进 /root
    echo $HOME 还是 /home/你的用户名 /root
    echo $PATH 基本还是你那套 root 那套
    提示符 常常还是 $(不变 #) #

    为什么这很坑:你用 su 进去,看着提示符是普通用户的样子,其实权限已经是 root 了——你以为自己在自己家目录里干活,实际上一抬手删的是 root 的东西。或者反过来:你以为已经「切到 root 环境」了,结果 pwd 还在别人目录下,一跑脚本路径全错。

    一句话记法:要变成 root 干活,就敲 su -(带减号);不带减号的 su 是「只换身份、不动环境」,日常几乎不该用。

    那 sudo su 是什么?就是用 sudo 的密码机制去执行 su——问你的密码、不用 root 密码。它等价于一次「保留环境的提权」,所以常见的老教程写:

    sudo su     ≡ 用你自己的密码,变成 root(保留环境)
    sudo su –   ≡ 用你自己的密码,变成 root(完整登录环境)
    sudo -i     ≈ sudo su – (推荐写法,更短、更标准)

    结论:想在 Ubuntu 上变成 root,敲 sudo -i。老教程里的 su root 在这台机器上永远进不去,sudo su 能进去但啰嗦。

    六、决策表:什么场景用哪个

    你要干的事敲什么为什么
    装软件、重启服务、改一个系统配置文件 sudo 命令 只借这一次,风险最小
    要连着敲十几条 root 命令(比如配环境) sudo -i 一次进入 root 登录环境,路径和别名都对
    只想保留自己环境,但让某条命令以 root 跑 sudo 命令 或 sudo -E 命令 环境不变,行为可预期
    教程让你 su root 换成 sudo -i Ubuntu 上 root 是锁的,su 进不去
    要看一下自己被允许提权到什么程度 sudo -l 安全体检的第一步
    走人前想作废免密窗口 sudo -k 别人接手这台机器时不会白捡 root

    七、四个坑

    坑 1:以为 su 和 su – 差不多。 差在环境:su 保留你的目录、HOME、PATH,su – 才是真正的 root 登录环境。用 pwd 和 echo $HOME 一比就知道。带减号的那个才是「变成 root」。

    坑 2:为了能用 su,给 root 设一个密码。

    sudo passwd root            # ← 能设,但先看完这段再决定

    设完确实能 su 了,代价是:这台机器从此多了一个可以被密码猜的 root 账号。Ubuntu 默认锁着 root,正是为了堵死这条路;一旦设了密码,如果还开了 SSH 密码登录,暴力破解的目标就从「没密码的 root」变成了「有密码的 root」。

    要提权就 sudo -i,不需要给 root 设密码。

    坑 3:在 root 里再套一层 sudo。 sudo -i 之后你已经就是 root 了,再敲 sudo 纯属多余;在某些没有终端的环境(脚本、CI)里还会直接报 sudo: a terminal is required to read the password。

    坑 4:sudo echo … > /root/文件 写不进去。

    这条最隐蔽。看这个例子:

    $ sudo echo "hello" > /root/test.txt
    bash: /root/test.txt: 权限不够

    为什么加了 sudo 还说权限不够? 因为这条命令实际干的事有两步:

  • sudo echo "hello" —— 这一步确实是 root 在跑;

  • > /root/test.txt —— 这个重定向是「你的 shell」做的,不是 root 做的。

  • shell 拿着你的身份去开 /root/test.txt,权限自然不够。sudo 只管住了命令,没管住重定向。

    正确写法是让「写文件」这个动作也被 root 执行:

    $ echo "hello" | sudo tee /root/test.txt
    hello

    怎么读:tee 的作用是「把标准输入同时写到文件和屏幕」,所以它既完成了写入,又把内容回显出来(上面那个 hello 就是它打印的)。记住这个组合:要往只有 root 能写的地方写文件,用 | sudo tee 文件,不要用 sudo … >。

    速查表(文末收藏版)

    我现在是谁           → whoami / id
    看 root 有没有密码   → sudo passwd -S root   (第二位 L=锁定,P=有密码)
                            sudo grep ^root: /etc/shadow (第 2 段:! 锁 / $y$·$6$ 有密码)
    变成 root(Ubuntu)   → sudo -i               (要自己的密码)
    变 root(有 root 密码)→ su –                 (带减号才对)
    只看提权权限         → sudo -l
    提权后立刻收回       → sudo -k
    sudo 的 PATH 从哪来   → sudo grep -n secure_path /etc/sudoers
    你的 PATH 从哪来     → cat /etc/environment
    sudo 后命令找不到     → 多半是 secure_path 里没有那个目录
    往 root 目录写文件   → echo 内容 | sudo tee 文件   (不能用 sudo … > )
    属于哪个提权组       → Ubuntu: sudo 组 / RHEL: wheel 组
    提权日志在哪         → /var/log/auth.log

    赞(0)
    未经允许不得转载:171主机测评 » 用户权限 01|su、sudo、sudo su、sudo -i 到底差在哪?先花两分钟搞懂 root 和普通用户
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址