sudo -i 和 sudo su 的区别

Luc*_*man 21 su sudo command

sudo -i和 和有sudo su什么区别?

slm*_*slm 29

根据手册页中的描述susudo我会假设以下事情。

  1. 因为sudo -iu <user>意味着一个登录shell,这相当于一个su - <user>or su -l <user>
  2. 一个su不带任何参数改变你的有效用户ID,但您使用的仍是原来的<user>环境和who am i会报告你还在<user>

摘录 sudo 手册页

-i [command]
        The -i (simulate initial login) option runs the shell specified in
        the passwd(5) entry of the target user as a login shell.  This means
        that login-specific resource files such as .profile or .login will 
        be read by the shell.  If a command is specified, it is passed to 
        the shell for execution.  Otherwise, an interactive shell is 
        executed.  sudo attempts to change to that user's home directory 
        before running the shell.  It also initializes the environment, 
        leaving DISPLAY and TERM unchanged, setting HOME, MAIL, SHELL, 
        USER, LOGNAME, and PATH, as well as the contents of 
        /etc/environment on Linux and AIX systems.  All other environment 
        variables are removed.
Run Code Online (Sandbox Code Playgroud)

例子

我有一个用户帐户,samlUID 为 500。

$ egrep "Uid|Gid" /proc/$$/task/$$/status
Uid:    500 500 500 500
Gid:    501 501 501 501
Run Code Online (Sandbox Code Playgroud)

在上面的输出中,第一列是我的真实 UID (uid),第二列是我的有效 UID (euid)。

通过 (su) 成为 root

$ su
Run Code Online (Sandbox Code Playgroud)

现在我是 root,但我仍然维护我的环境,我真正的 UID 仍然是500. 请注意,我的 euid 现在为 0(根)。

$ egrep "Uid|Gid" /proc/$(pgrep su -n)/task/$(pgrep su -n)/status
Uid:    500 0   0   0
Gid:    501 501 501 501
Run Code Online (Sandbox Code Playgroud)

但是我的环境仍然saml是。这是环境变量之一,$LOGNAME.

$ env | grep LOGNAME
LOGNAME=saml
Run Code Online (Sandbox Code Playgroud)

通过 (su -) 或 (sudo -i) 成为 root

$ su -
Run Code Online (Sandbox Code Playgroud)

使用su -orsudo -i不仅将我的有效 UID 更改为新用户,而且我还获取他们的文件,就好像它是登录一样,我的环境现在变得完全相同,就好像我是他们直接登录一样。

$ egrep "Uid|Gid" /proc/$(pgrep su -n)/task/$(pgrep su -n)/status
Uid:    500 0   0   0
Gid:    501 501 501 501
Run Code Online (Sandbox Code Playgroud)

但是我的环境是现在root的。相同的变量 ,$LOGNAME现在设置为root

$ env | grep LOGNAME
LOGNAME=root
Run Code Online (Sandbox Code Playgroud)

那么有什么区别呢?

好吧,让我们试试上面的方法sudo -i并找出答案。

$ sudo -i
Run Code Online (Sandbox Code Playgroud)

现在让我们看看相同的信息:

$ egrep "Uid|Gid" /proc/$(pgrep su -n)/task/$(pgrep su -n)/status
Uid:    0   0   0   0
Gid:    501 501 501 501
Run Code Online (Sandbox Code Playgroud)

嗯,一件主要的事情是我的有效 ID 和真实 ID 都是 0 ( root) 使用这种方法。环境变量$LOGNAME就像我们以root.

$ env | grep LOGNAME
LOGNAME=root
Run Code Online (Sandbox Code Playgroud)

比较环境

如果我们计算 3 种方法中的行数,也许还有一些额外的信息。

$ env > /tmp/<method used to become root>
Run Code Online (Sandbox Code Playgroud)

我们只剩下这 3 个文件:

  • -rw-r--r-- 1 根 1999 年 11 月 2 日 06:43 sudo_root.txt
  • -rw-r--r-- 1 根 1970 年 11 月 2 日 06:44 sudash_root.txt
  • -rw-r--r-- 1 根 4859 十一月 2 日 06:44 su_root.txt

我们已经可以看到,只是一个普通的su. 环境。是其他尺寸的 2 倍以上。

每个中的行数:

$ wc -l su*
  28 sudash_root.txt
  32 sudo_root.txt
  92 su_root.txt
Run Code Online (Sandbox Code Playgroud)

真的没有必要进一步查看su_root.txt文件。该文件包含运行该su命令的大部分用户环境。所以让我们看看其他 2 个文件。

除了一些外观变量外,它们几乎相同,例如$LANG略有不同。列表中的一支吸烟枪是$PATH.

须藤

 PATH=/usr/lib64/ccache:/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/brlcad/bin:/root/bin
Run Code Online (Sandbox Code Playgroud)

苏——

PATH=/usr/lib64/qt-3.3/bin:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/brlcad/bin:/root/bin
Run Code Online (Sandbox Code Playgroud)

正如您所看到的sudo -i,通过去除可疑路径为我们提供了一些额外的保护,但如果我们将 GUI 显示到不同的位置,它也会保持我们的$DISPLAY$TERM完整的。

带走?

  1. 所以最大的收获是用于成为 root 的方法sudo -i比其他方法有优势,因为你使用自己的密码来这样做,保护 root 的密码不需要被泄露。
  2. 当你成为时有日志记录root,而神秘地root通过susu -
  3. sudo -i为您提供更好的用户体验,su因为它可以保护您的$DISPLAY$TERM
  4. sudo -i当用户成为 时root,通过限制他们所处的环境,为系统提供一些保护。

怎么样sudo su,你连讨论都没有?

我故意避免将其纳入讨论,即使 OP 询问它,因为这样做只会混淆问题,IMO。当您运行sudo susudo命令时su,您将从常规环境中获得的许多环境效果都将被屏蔽su。须藤做其工作,并不管它是提供限制和受保护的环境sudo susudo -i

例子

这是sudo su环境被转储的结果:

ls -l /tmp/sudosu_root.txt
-rw-r--r-- 1 root root 1933 Nov  2 14:48 /tmp/sudosu_root.txt
Run Code Online (Sandbox Code Playgroud)

和行数:

$ wc -l /tmp/sudosu_root.txt 
31 /tmp/sudosu_root.txt
Run Code Online (Sandbox Code Playgroud)

这些是 asudo su -和 a之间唯一不同的变量sudo -i

$ sdiff /tmp/sudosu_root.txt /tmp/sudo_root.txt  | grep ' |'
USERNAME=saml                             | USERNAME=root
PATH=/usr/lib64/ccache:/sbin:/bin:/usr/sbin:/usr/bin:/usr/brl | PATH=/usr/lib64/ccache:/usr/local/sbin:/sbin:/bin:/usr/sbin:/
MAIL=/var/spool/mail/saml                 | MAIL=/var/spool/mail/root
PWD=/home/saml/tst                        | PWD=/root
SUDO_COMMAND=/bin/su                      | SUDO_COMMAND=/bin/bash
XAUTHORITY=/root/.xauthYFtlL3             | XAUTHORITY=/var/run/gdm/auth-for-saml-iZePuv/datab
Run Code Online (Sandbox Code Playgroud)

因此,正如您所看到的,它们之间确实没有太大区别。略有不同$PATH$SUDO_COMMAND、 和$MAIL$USERNAME是唯一的区别。

参考

  • `sudo` 和 `su` 都通过 PAM 堆栈。如果它在一个下登录,它应该在另一个下登录。此外,`sudo su` 会像 `sudo -i` 一样剥离环境。事实上,我没有看到您在答案中的任何地方提到“sudo su”... (2认同)

phe*_*mer 6

我认为@slm 误读了这个问题,所以提供另一个答案。

他确实抓住了要点,关于一个是登录 shell,另一个不是。
运行时sudo -ishell 将成为登录 shell,因此它会读取诸如~/.profilewhere 之类的内容,而非登录 shell 只会读取~/.bashrc.

sudosu(如sudo su)链接时, thesudo和 the都不会su调用登录shell。等效于sudo -i使用时su将改为sudo su -l.

我个人认为sudo su是“无用的使用 cat”的例子。您可以使用sudo -s.

基本上有 5 种通过 sudo 调用 root shell 的常用方法

  • sudo su

    • 非登录外壳
    • 设置HOME/root
    • 修剪环境
  • sudo -i

    • 登录外壳
    • 设置HOME/root
    • 修剪环境
  • sudo su -l

    • 登录外壳
    • 设置HOME/root
    • 修剪环境

    调用shell时,这相当于 sudo -i

  • sudo -s

    • 非登录外壳
    • 设置HOME/root
    • 修剪环境

    调用shell时,这相当于 sudo su

  • sudo -Es

    • 非登录外壳
    • HOME独自离开
    • 离开环境(除了$PATH$LD_LIBRARY_PATHiirc)

请注意,这些规则仅适用于使用它们获得外壳的情况。sudo -s somecommand和之间有区别sudo su -c somecommand