Linux命令:su和sudo的区别

作者:Administrator 发布时间: 2021-11-23 阅读量:18 评论数:0

之前一直对 su 和 sudo 这两个命令的区别不清楚,最近专门搜了这方面的资料,总算是把两者的关系以及用法搞清楚了,这篇文章来系统总结一下。

1. 准备工作

需要新建立多用户 Linux 中新建用户的命令是useradd ,一般系统中这个命令对应的路径都在 PATH 环境变量里,如果直接输入 useradd 不管用的话,就用绝对路径名的方式:/usr/sbin/useradd 。 useradd 新建用户命令只有 root 用户才能执行,我们先从普通用户 user 切换到 root 用户

user@VM-0-14-ubuntu:~$ su - Password               #输入 root 用户登录密码
root@VM-0-14-ubuntu:~# useradd -m test_user        #带上 -m 参数
root@VM-0-14-ubuntu:~# ls /hometest_user user      #可以看到 /home 目录下面有两个用户了

因为还没有给新建的用户 test_user 设置登录密码,这就导致我们无法从普通用户 user 切换到 test_user,所以接下来,我们需要用 root 来设置 test_user 的登录密码。需要用到 passwd 命令:

root@VM-0-14-ubuntu:~# passwd test_userEnter new UNIX password:       #输出 test_user 的密码
Retype new UNIX password:passwd: password updated successfully!
root@VM-0-14 -ubuntu:~#
root@VM-0-14-ubuntu:~#
exit                                                                  #输入 exit 退出 root 用户到 普通用户
logoutuser@VM-0-14-ubuntu:~$                                          #可以看到,命令提示符前面已经由root变成$

如果有上述显示,说明我们现在的身份是 user 用户。

2. su 命令介绍及主要用法

首先需要解释下 su 代表什么意思。之前一直以为 su 是 super user,查阅资料之后才知道原来表示 switch user。知道 su 是由什么缩写来的之后,那么它提供的功能就显而易见了,就是切换用户。

2.1 - 参数

su 的一般使用方法是: su <user_name >或者 su - <user_name >两种方法只差了一个字符 -,会有比较大的差异:

login-shell方式和non-login-shell方式的区别

login-shell 的方式

non-login-shell的方式

加载对应用户的环境变量和各种设置

所有配置是切换之前用户的环境变量以及各种设置

2.1.1 - 概念
  • login shell: 取得 bash 时需要完整的登陆流程的,就称为 login shell。我们登陆shell时,需要输入用户的账号与密码,此时取得的 bash 就称为login shell。

  • non-login shell:取得 bash 接口的方法不需要重复登陆,我们登陆 Linux 后,启动终端Terminal,此时终端接口并没有需要再次的输入账号与密码,这时bash 的环境就称为 non-login shell。又或者你在原本的 bash 环境下再次使用 bash命令,作为bash的子进程,同样的也没有输入账号密码, 那么第二个 bash (子程序) 也是 non-login shell 。


只解释会比较抽象,我们看一个例子就比较容易理解了。我们首先从 user用户以 login-shell 的方式切换到 root 用户,再用non-login-shell,比较两种用户状态下环境变量中 PWD 的值(su 命令不跟任何,默认切换到 root 用户):

user@VM-0-14-ubuntu:~$ su user          #login-shell 方式
Password:                               # 输入 user 用户登录密码
user@VM-0-14-ubuntu:~$ env | grep use
PWD=/home/user
USER=user
Home=/home/user

user@VM-0-14-ubuntu:~$

此时是PWD=/home/user HOME=/home/user

user@VM-0-14-ubuntu:~$ su               # non-login-shell 方式
Password:                               # 输入 root 用户登录密码
root@VM-0-14-ubuntu:/home/user# env | grep user
PWD=/home/user                          # 可以发现还是 /home/user
USER=rootHOME=/root                     # Home目录变为了 /root 
root@VM-0-14-ubuntu:/home/user          # 我们切换到 root 用户了,但shell的环境变量并没有改变

此时是PWD=/home/user HOME=/root

测试后发现:

  • login-shell 的方式切换用户,shell 中的环境变量会随之改变。

  • non-login-shell方式,也就是登录方式切换用户,shell中的环境变量不会变更

2.1.2 - 总结:

具体使用哪种方式切换用户看个人需求:

  • 1) 如果不想因为切换到另一个用户导致自己在当前用户下的设置不可用,那么用 non-login-shell 的方式;

  • 2 )如果切换用户后,需要用到该用户的各种环境变量,那么使用 login-shell 的方式。

2.2 切换到指定用户

前面已经介绍了,如果 su 命令后面不跟任何,那么默认是切换到 root 用户:

user@VM-0-14-ubuntu:~$ su
Password:                         # root 用户的密码
root@VM-0-14-ubuntu:/home/user#

因为我们在 准备工作部分已经新建了一个 test_user 用户,并且我们也知道 test_user 用户的登录密码,我们就能从 user用户切换到 test_user 用户:

user@VM-0-14-ubuntu:~$ su - test_user
Password:                                      # test_user 用户的密码
test_user@VM-0-14-ubuntu:~$                    # 切换到了test_user
2.3 -c 参数

前面的方法中,我们都是先切换到另一个用户(root 或者 test_user),在哪个用户的状态下执行命令,最后输入 exit 返回当前 user用户。还有一种方式是:不需要先切换用户再执行命令,可以直接在当前用户下,以另一个用户的方式执行命令,执行结束后就返回当前用户。这就得用到 -c 参数。具体使用方法是:

su - -c 指令串           # 以 root 的方式执行指令串

我们来看个例子:

user@VM-0-14-ubuntu:~$ cat /etc/shadow
cat/etc/shadow:  Permission denied                                # user用户不能直接查看 /etc/shadow 文件内容
user@VM-0-14-ubuntu:~$ su - -c tail -n 4 /etc/shadow
Password:                                                         # 输入 root 用户密码user: $1$fZKcWEDI$uwZ64uFvVbwpHTbCSgim0/:18352:0:99999:7:::ntp:*  :17752:0:99999:7:::mysql: !:18376:0:99999:7:::test_user: $6$.ZY1lj4m$ii0x9CG8h.JHlh6zKbfBXRuolJmIDBHAd5eqhvW7lbUQXTRS/ /89jcuTzRilKqRkP8YbYW4VPxmTVHWRLYNGS/:18406:0:99999:7:::
user@VM-0-14-ubuntu:~$                                            # 执行完马上返回 user用户而不是 root 用户

这种执行方式和后面要介绍的sudo很像, 都是临时申请一下root用户的权限。

3. sudo 命令介绍及主要用法

sudo的英文全称是 super user do,即以超级用户(root 用户)的方式执行命令。这里的 sudo 和之前 su 表示的 switch user 不同。

3.1 主要用法

我们在 Linux 中经常会碰到 Permission denied 这种情况,比如以 user用户的身份查看 /etc/shadow 的内容。因为这个文件的内容是只有 root 用户能查看的。这时候就可以使用 sudo :

user@VM-0-14-ubuntu:~$ tail -n 3 /etc/shadow
tail:  cannot open '/etc/shadow' for reading:  Permission denied           # 没有权限
user@VM-0-14-ubuntu:  ~$ sudo !!                                           # sudo 执行重复命令
ntp:*:17752:0:99999:7:::mysql: !:18376:0:99999:7:::test_user: $6$.ZY1lj4m$ii0x9CG8h.JHlh6zKbfBXRuolJmIDBHAd5eqhvW7lbUQXTRS/ /89jcuTzRilKqRkP8YbYW4VPxmTVHWRLYNGS/:18406:0:99999:7:::
user@VM-0-14-ubuntu:~$

我们使用了 sudo 这个小技巧,表示重复上面输入的命令,只不过在!!最前面加上 sudo 。因为我已经设置了 sudo 命令不需要输入密码,所以这里 sudo 命令行 就能直接输出内容。如果没有设置的话,需要输入当前这个用户的密码。例如本例中,我就应该输入 user 用户的登录密码。两次相邻的 sudo 操作,如果间隔在 5min 之内,第二次输入 sudo 不需要重新输入密码;如果超过 5min,那么再输入 sudo 时,又需要输入密码。所以一个比较省事的方法是设置 sudo 操作不需要密码。

sudo su -这种方式也能以 login-shell 的方式切换到 root 用户,但是它和 su - 方法有区别。前者需要提供当前用户的登录密码,也就是 user 用户的密码;后者输入 su - 后,需要提供 root 用户的登录密码。还有一个命令: sudo -i这个命令和 sudo su - 效果一致,也是切换到 root 用户,也是需要提供当前用户(user 用户)的登录密码。我们现在切换到 test_user 用户,尝试显示 /etc/shadow 文件的内容:

user@VM-0-14-ubuntu:~$ su - test_user
Password:                                     # test_user 的密码
user@VM-0-14-ubuntu:~$ sudo cat /etc/shadow
password for test_user:                       # test_user 的密码
test_user is not in sudoers file. This incident will be reported.
user@VM-0-14-ubuntu:~$

我们会看到倒数第二行中的错误提示信息,我们无法查看 /etc/shadow 的内容,这就涉及到 sudo工作原理了。

3.2 sudo 工作原理

一个用户能否使用 sudo 命令,取决于 /etc/sudoers 文件的设置。从 3.1 节中我们已经看到,user 用户可以正常使用 sudo ,但是 test_user 用户却无法使用,这是因为 /etc/sudoers 文件里没有配置 test_user。 /etc/sudoers 也是一个文本文件,但是因其有特定的语法,我们最好不要直接用 vim 或者 vi 来编辑它,一旦出现语法错误,退出超级用户模式后就再也无法使用sudo;需要用 visudo 这个命令。输入这个命令之后就能直接编辑 /etc/sudoers 这个文件了。只有 root 用户有权限使用 visudo 命令。我们先来看下输入 visudo 命令后显示的内容。输入(root 用户):

root@VM-0-14-ubuntu:~# visudo

输出:

# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root    ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "#include" directives:

讲解:

  • root ALL=(ALL) ALL root表示被授权的用户,这里是根用户;

  • 第一个ALL表示所有计算机,第二个ALL表示所有用户,第三个ALL表示所有命令;全句的意思是:授权根用户在所有计算机上以所有用户的身份运行所有文件。

  • %admin ALL=(ALL) ALL同上面一样,只不过被授权的是admin这个组。

  • /etc/sudoers的通用格式为: user host run_as command user:

  • 一位或几位用户,在/etc/group中可以用一个%代替它,组对象的名称一定要用百分号%开头。

  • host:一个或几个主机名;

  • run_as:作为哪个用户运行,常见选项是rootALL command:想让用户或组运行的一个或几个根级别命令。

  • 例如: hans ALL=(root) useradd,userdel 授权hans用户在所有计算机上以root身份运行useradd,userdel命令。

  • %smith ALL=(ALL) NOPASSWD:useradd,userdel 授权smith组全部成员在所有计算机上以所有用户的身份运行useradd,userdel命令,且运行时不必输入密码。

    includedir /目录 表示要引用某个目录里的文件

需要注意的是,当我们为用户定义可以运行的命令时,必须使用完整的命令路径。这样做是完全出于安全的考虑,如果我们给出的命令只是简单的useradd而非 /usr/sbin/useradd,那么用户有可能创建一个他自己的脚本,也叫做useradd,然后放在它的本地路径中,如此一来他就能够通过这个名为 useradd 的本地脚本,作为root来执行任何他想要的命令了。这是相当危险的!

按照这个思路,我们把 test_user 添加到 /etc/sudoers 文件中,使 test_user 也能使用 sudo 命令。我们在最后一行添加:

test_user ALL=(ALL:ALL) ALL        # test_user 使用 sudo 需要提供 test_user 的密码

接下来我们再在 test_user 账户下执行 sudo :

user@VM-0-14-ubuntu:~$ su - test_user
Password:
user@VM-0-14-ubuntu:~$ tail -n 3  /etc/shadow
tail: cannot open '/etc/shadow' for reading: Permission denied     #没有访问权限
user@VM-0-14-ubuntu:~$ sudo tail -n 3  /etc/shadow                 # 加上 sudo
ntp:*:17752:0:99999:7:::mysql:!:18376:0:99999:7:::test_user: $6$.ZY1lj4m$ii0x9CG8h.JHlh6zKbfBXRuolJmIDBHAd5eqhvW7lbUQXTRS/ /89jcuTzRilKqRkP8YbYW4VPxmTVHWRLYNGS/:18406:0:99999:7:::
user@VM-0-14-ubuntu:~$

可以看到,现在已经可以使用 sudo 了。

3.3 思考

我们已经看到了,如果一个用户在 /etc/sudoers 文件中,那么它就具有 sudo 权限,就能通过 sudo su - 或者 sudo -i 等命令切换到 root 用户了,那这时这个用户就变成 root 用户了,那这不对系统造成很大的威胁吗?实际上的确是这样的。所以如果在编辑 /etc/sudoers 文件赋予某种用户 sudo 权限时,必须要确定该用户是可信任的,不会对系统造成恶意破坏,否则将所有 root 权限都赋予该用户将会有非常大的危险。当然,root 用户也可以编辑 /etc/sudoers 使用户只具备一部分权限,即只能执行一小部分命令。当然,root 用户也可以编辑 /etc/sudoers 使用户只具备一部分权限,即只能执行一小部分命令。有兴趣的可以参考 Reference 部分第二条,这篇文章不再赘述。

4. 二者的差异对比

我们已经看到: - 使用 su - ,提供 root 账户的密码,可以切换到 root 用户;使用 sudo su - ,提供当前用户的密码,也可以切换到 root 用户 两种方式的差异也显而易见:如果我们的 Linux 系统有很多用户需要使用的话,前者要求所有用户都知道 root 用户的密码,这显然是非常危险的;后者是不需要暴露 root 账户密码的,用户只需要输入自己的账户密码就可以,而且哪些用户可以切换到 root,这完全是受 root 控制的(root 通过设置/etc/sudoers实现的),这样系统就安全很多了。一般都是推荐使用 sudo 方式。

References

  • https://www.rootusers.com/the-difference-between-su-and-sudo-commands-in-linux/

  • 《鸟哥的 Linux 私房菜》13.4 节:使用者身份切换

  • https://github.com/ustclug/Linux101-docs/blob/master/docs/Ch05/index.md

  • https://www.maketecheasier.com/differences-between-su-sudo-su-sudo-s-sudo-i/

  • https://stackoverflow.com/questions/35999671/whats-the-difference-between-sudo-i-and-sudo-su?r=SearchResults

  • https://www.zhihu.com/question/51746286

  • https://www.linuxidc.com/Linux/2017-06/144916.htm

评论