【Linux】 su 和 sudo 的区别剖析

时间:2024-10-27 13:25:37

目录

一、概述

二、su 命令介绍及主要用法

2.1 参数-

2.2 切换到指定用户

2.3 参数-c

三、sudo 命令介绍及主要用法

3.1 主要用法

3.2 sudo 工作原理

四、二者的差异对比


一、概述


Linux 中新建用户的命令是 useradd ,一般系统中这个命令对应的路径都在 PATH 环境变量里,如果直接输入 useradd 不管用的话,就用绝对路径名的方式:/usr/sbin/useradd

useradd 新建用户命令只有 root 用户才能执行,我们新建用户kangll ,并设置密码。


二、su 命令介绍及主要用法


首先需要解释下 su 代表什么意思。su 表示 switch user,它提供的功能就是切换用户。

官方释义:

su允许运行带有替代用户和组ID的命令。当不带参数调用时,su默认以root身份运行交互式shell。为了向后兼容,su默认不更改当前目录,并且只设置环境变量HOME和SHELL(如果目标用户不是根用户,则加上USER和LOGNAME)。建议始终使用 --login选项(而不是它的快捷方式-),以避免混合环境造成的副作用。

这个版本的su使用PAM进行身份验证、帐户和会话管理。一些其他su实现中的配置选项(例如对wheel组的支持)必须通过PAM进行配置。

su主要是为非特权用户设计的,这是特权用户的推荐解决方案。

2.1 参数-

su 的一般使用方法是:

su  <user_name>  

或者

su - <user_name>  

两种方法只差了一个字符 -会有比较大的差异

  • 如果加入了 - 参数,那么是一种 login-shell 的方式,意思是说切换到另一个用户 <user_name> 之后,当前的 shell 会加载 <user_name> 对应的环境变量和各种设置;
  • 如果没有加入 - 参数,那么是一种 non-login-shell 的方式,意思是说我现在切换到了 <user_name>,但是当前的 shell 还是加载切换之前的那个用户的环境变量以及各种设置。

光解释会比较抽象,我们看一个例子就比较容易理解了。

我们从kangll 用户以 non-login-shell 的方式切换到 root 用户,比较两种用户状态下环境变量中 PWD 的值(su 命令不跟任何 <user_name> ,默认切换到 root 用户):

我们的确是切换到 root用户了,但是 shell 环境中的变量并没有改变,还是用之前 kangll 用户的环境变量。

接着我们从 kangll 用户以 login-shell 的方式切换到 root 用户,同样比较两种用户转台下环境变量中 PWD 的值:

可以看到用 login-shell 的方式切换用户的话,shell 中的环境变量也跟着改变了。

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

  • 如果不想因为切换到另一个用户导致自己在当前用户下的设置不可用,那么用 non-login-shell 的方式;
  • 如果切换用户后,需要用到该用户的各种环境变量(不同用户的环境变量设置一般是不同的),那么使用 login-shell 的方式。

2.2 切换到指定用户

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

如下我们可以从 mysql 用户切换到 kangll 用户:

2.3 参数-c

前面的方法中,我们都是先切换到另一个用户(root 或者 kangll),在哪个用户的状态下执行命令,最后输入 exit 返回到当前用户。

还有一种方式是:不需要先切换用户再执行命令,可以直接在当前用户下,以另一个用户的方式执行命令,执行结束后就返回当前用户。这就得用到 -c 参数。

具体使用方法是:

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

看个例子:

这种执行方式一般是我们想以某个用户启动一个特定的进程,比如下面后台启动hive进程:

su - hive -c  'env HADOOP_HOME=//usr/hdp/2.6.4.0-91/hadoop nohup hive --service metastore > /var/log/hive/hive.out 2> /var/log/hive/hive.log &'

三、sudo 命令介绍及主要用法


sudo 的英文全称是 super user do,即以超级用户(root 用户)的方式执行命令。这里的 sudo 和之前 su 表示的 switch user 是不同的,这点需要注意,很容易搞混。

我们先介绍 sudo 命令能做什么事情。

3.1 主要用法

我们在 Linux 中经常会碰到 Permission denied 这种情况,比如以 kangll 用户的身份查看 /etc/profile 的内容。因为这个文件的内容是只有 root 用户能查看的。

那如果我们想要查看怎么办呢?这时候就可以使用 sudo :

需要输入当前这个用户的密码,本例中需要输入 knagll 用户的登录密码。

两次相邻的 sudo 操作,如果间隔在 5min 之内,第二次输入 sudo 不需要重新输入密码;如果超过 5min,那么再输入 sudo 时,又需要输入密码。所以一个比较省事的方法是设置 sudo 操作不需要密码,后面我们将介绍如何设置。

sudo 除了以 root 用户的权限执行命令外,还有其它几个用法,这里做简单介绍。

切换到 root 用户:

sudo su -  

这种方式也能以 login-shell 的方式切换到 root 用户,但是它和 su - 方法是由区别的:

  • 前者输入 sudo su - 后,需要提供当前用户的登录密码,也就是 kangll 用户的密码;
  • 后者输入 su - 后,是切换到root用户,需要提供 root 用户的登录密码。

还有一个命令:

sudo -i

这个命令和 sudo su - 效果一致,也是切换到 root 用户,也是需要提供当前用户(ubuntu 用户)的登录密码。

我们现在切换到 winner 用户,尝试显示 /etc/shadow 文件的内容:

我们会看到错误提示信息,并无法查看 /etc/shadow 的内容,这就需要为普通用户设置sudo权限。

3.2 sudo 工作原理

一个用户能否使用 sudo 命令,取决于 /etc/sudoers 文件的设置。

从上节我们已经看到,kangll 用户可以正常使用 sudo ,这是因为 /etc/sudoers 文件里做了设置。

/etc/sudoers 是一个文本文件,但是因其有特定的语法,我们一般不直接用 vim 或者 vi 来编辑它,需要用 visudo 这个命令。输入这个命令之后就能直接编辑文件 /etc/sudoers 。需要注意的是,只有 root 用户有权限使用 visudo 命令。

我们先来看下输入 visudo 命令后显示的内容。

[root@windp-aio ~]# visudo

输出:

## Allow root to run any commands anywhere 
root	ALL=(ALL) 	ALL

## Allows members of the 'sys' group to run networking, software, 
## service management apps and more.
# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS

## Allows people in group wheel to run all commands
%wheel	ALL=(ALL)	ALL

## Same thing without a password
# %wheel	ALL=(ALL)	NOPASSWD: ALL
kangll	        ALL=(ALL)	 ALL

## Allows members of the users group to mount and unmount the 
## cdrom as root
# %users  ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom

## Allows members of the users group to shutdown this system
# %users  localhost=/sbin/shutdown -h now

## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment)
#includedir /etc/sudoers.d

解释下每一行的格式:

  • 第一个表示用户名,如 root 、kangll 等;
  • 接下来等号左边的 ALL 表示允许从任何主机登录当前的用户账户;
  • 等号右边的 ALL 表示:这一行行首用户可以切换到系统中任何一个其它用户;
  • 行尾的 ALL 表示:当前行首的用户,能以 root 用户的身份下达什么命令,ALL 表示可以下达任何命令。

我们还注意到 kangll 对应的那一行有个 NOPASSWD 关键字,这就是表明 kangll 这个用户在请求 sudo 时不需要输入密码,到这里就解释了前面的问题。

同时这个文件里并没有 winner 对应的行,这也就解释了为什么 winner 无法使用 sudo 命令。

接下来,我们尝试将 winner 添加到 /etc/sudoers 文件中,使 winner 也能使用 sudo 命令。我们在最后一行添加:

# winner 使用 sudo 不需要提供密码 ,且后面对操作目录做了限制
winner ALL=(ALL) NOPASSWD:ALL,!/usr/bin/su,!/usr/bin/chattr,!/usr/sbin/init,!/usr/sbin/reboot,!/sbin/reboot,!/usr/sbin/shutdown,!/usr/bin/passwd,!/bin/bash,!/bin/sh
  • winner表示的是开发用户
  • NOPASSWD:ALL表示sudo命令可以免密使用
  • !/usr/bin/su表示禁止使用sudo su -
  • !/usr/sbin/iptables表示禁止使用reboot
  • !/bin/chattr表示禁止使用chattr

如上特别注意命令需要加上绝对路径。

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

可以看到,现在已经可以使用 sudo 了,限制的命令也起作用了。


四、二者的差异对比


我们可以看到:

  • 使用 su - ,提供 root 账户的密码,可以切换到 root 用户;
  • 使用 sudo su - ,提供当前用户的密码,也可以切换到 root 用户

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


参考文章:面试被问 Linux su 和 sudo 的区别?感觉自己白学了!