掘金 后端 ( ) • 2022-12-02 08:35

“ 本文正在参加「金石计划 . 瓜分6万现金大奖」 ”

14.12 Linux用户身份切换命令su

在Linux系统中,由于超级用户root的权限太大了,如果管理不好,就会带来严重的系统安全隐患。因此在工作场景中,只在必要时才使用超级用户权限。一般临时性工作处理,都是以普通用户的身份完成的,那么当普通用户需要超级用户的权限时,又是如何进行切换管理的呢?这就不得不提到两个重要的用户身份切换命令su和sudo了。下面就来讲解这两个命令是如何通过用户切换来达到系统管理目的的。

14.12.1 su命令介绍

简单地说,su命令就是切换用户身份的命令。比如,以普通用户neteagle登录到系统之后,当在系统中执行useradd添加用户时,会发现neteagle用户没有这个权限,这个权限只能由root权限来执行。解决办法之一就是退出neteagle用户,重新以root用户的身份登录。方法二是直接在neteagle用户下,使用su命令来切换到root用户下进行用户添加的工作,等工作完成后,再退出root用户。毫无疑问,上面这两个方法比较起来,通过su命令切换是一种比较好的办法。

su命令可以在用户之间进行切换,超级权限用户root向普通用户切换不需要密码验证(这就是超级权限所在),其他普通用户之间或者从普通用户切换到root,都需要切换用户的密码验证。

14.12.2 su命令用法

【语法格式】

su [option] [user]
su [选项] [用户名]

说明:

1)若命令后面的用户名省略了,则默认切换为root用户。

2)从root用户切换到普通用户时,不需要任何密码,从普通用户切换到root用户时,则需要输入root密码。

【选项说明】

为了方便读者查看,表14-15展示了su命令的常用参数选项列表。

表14-15 su命令的参数选项

b14-15.png

在生产场景中,su命令比较常用的参数为“-”和"-c",其他的参数很少用到。如果读者有兴趣,可执行man su进行查看。

14.12.3 su命令的使用范例

若不添加任何参数执行su命令,则表示要切换到root用户,但是这样执行,会遇到一些问题。因为虽然是切换到root用户了,但是并没有改变root用户登录后的环境,有些登录的环境设置还是登录前的用户的。生产厂家规范的操作方法是“su -”。具体实现请参见下面的示例。

范例14-19: 由普通用户neteagle切换到root用户。

[C:~]$ ssh [email protected]
​
​
Connecting to 10.0.0.201:22...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
​
WARNING! The remote SSH server rejected X11 forwarding request.
Last login: Sat Oct 17 20:44:31 2020
Wellcome to Linux!
[neteagle@centos7 ~]$ whoami    #当前登录的用户为普通用户neteagle。
neteagle
[neteagle@centos7 ~]$ su root   #切换用户,若切换的用户为root,则可以省略不写。
Password:   #这里当然就是root用户的密码了。
​
[root@centos7 /home/neteagle]# env |egrep   "USER|MAIL|PWD|LOGNAME"     #查看当前登录用户root的环境变量。
USER=neteagle
MAIL=/var/spool/mail/neteagle
PWD=/home/neteagle  #已经登录到root了,为什么家目录还是/home/neteagle呢?
LOGNAME=neteagle

细心的读者应该已经看到了,如果使用su而不加上“-”这个参数,那么切换前的用户的环境信息还会存在,这会引起很多麻烦,甚至还会出现意想不到的结果。因此,切换用户时,最好是"su - 用户名"。这是生产场景中标准的切换用户的操作方法。

退出到普通用户重新测试,命令如下:

[root@centos7 /home/neteagle]# exit
[neteagle@centos7 ~]$ su - root #第二种切换用户的方式,使用参数"-",root可省略。
Password: 
Last login: Sun Oct 18 16:32:33 CST 2020 on pts/1
[root@centos7 ~]# env |egrep "USER|MAIL|PWD|LOGNAME"    #再次查看环境变量。
USER=root
MAIL=/var/spool/mail/root
PWD=/root
LOGNAME=root

这回环境变量的内容都已经切换到root下了,这里需要提醒一下的是,不只是切换到root,切换到其他用户也是一样。

从上面的范例可以得出如下结论。

  • "su 用户名"虽然能够切换到对应用户,但是登录后的环境变量信息有些还是切换前用户的环境变量信息。

  • “su - 用户名”不但能切换到相应的用户,还能将登录后的环境变量一并切换,这是标准规范的操作方法。

    范例14-20: neteagle用户使用root身份执行命令。

    [neteagle@centos7 ~]$ ll /root  #直接在普通用户neteagle下执行命令是不允许的。
    ls: cannot open directory /root: Permission denied
    [neteagle@centos7 ~]$ su - -c "ls -l /root" #这是su的参数组合,表示切换到root用户,并且改变到root环境,然后列出root家目录的文件,最后退出root用户。
    Password:   #在这里输入root的密码,注意,这与后文要讲的sudo是有区别的。
    total 20
    -rw-------. 1 root root 1712 Oct  1 14:49 anaconda-ks.cfg
    

    范例14-21: 如何让系统在每次开机时自动以普通用户身份启动指定服务脚本?

    [neteagle@centos7 ~]$ tail -1 /etc/rc.local #在开机启动文件/etc/rc.local中写入启动命令。
    su - neteagle -c '/bin/sh /server/scripts/deploy.sh'    #以普通用户身份执行脚本,但并不是在用户的下面。
    

    提示: 除此之外还有很多方法,例如,可以进入到普通用户下再执行该脚本。

    通过普通用户运行服务是一个很好的提升系统安全性的办法,在生产环境中,大多数服务都可以通过普通用户启动(不使用特权端口),而不用root用户启动。这样就可以使系统的安全性又提高一个等级,同时使用普通用户管理就可以了,管理者不需要具体root权限。

14.12.4 su命令总结

  • 普通用户切换到root用户,可使用su -或su - root,但必须输入root密码才能完成切换。
  • root用户切换到普通用户,可使用“su - 普通用户名”的写法。不需要输入任何密码就能完成切换。在CentOS 5.X系统中,切换到普通用户后,在执行一些命令如ifconfig时,可能会遇到环境变量PATH路径问题,也会因此找不到某些命令(一般是/sbin、/usr/sbin等下面的命令),这时就需要使用全路径执行或者调整配置普通用户的PATH变量内容,CentOS 6和CentOS 7不存在这方面的问题。
  • 如果仅希望在某用户下执行命令,而不直接切换到该用户下操作,则可以使用"su - 用户名 -c 命令"的方式。

14.12.5 su命令的优缺点

毫无疑问,切换用户身份的su命令为系统管理员管理Linux系统带来了很多方便,将用户身份切换到root下,可以完成各种系统管理工作。任何一个普通用户只要知道了root用户的命,就都能以普通用户的身份切换到root来完成本来无法完成的系统管理的工作。

但是,这与通过su命令切换到root的操作也带来了很大的安全管理问题;比如系统有8个普通用户,都可以切换到root身份进行系统管理,甚至还可以改掉root的密码,让其他的普通用户无法再实现系统管理,还有,这么多用户中,有任何一人对系统操作存在重大失误,都可能导致整个系统奔溃或数据损失。这与的非集权式管理,在一定程度上对系统的安全性造成了较大的威胁。在工作中几乎有一半是来自内部。

所以,使用su命令切换身份对于多个系统管理员共同管理的场合,并不是最后的选择,笔者的意见是,如果是一般的中小公司,不超过3个管理员,那么为了管理方便,使用su来共同管理还是可以接受的。

我们既希望超级用户root密码掌握在少数或唯一的管理员手中,又希望多个系统管理员能够完成更多更复杂的系统管理的工作。那么,如何解决多个系统管理员都能管理系统而又不让超级权限泛滥的需求呢?这就需要利用sudo命令替代或结合su命令来完成这样苛刻且必要的管理需求。

14.13 visudo:编辑sudoers文件的工具

14.13.1 visudo命令介绍

visudo命令是专门用来编辑/etc/sudoers这个文件的,同时它还提供了语法检查等功能。/etc/sudoers文件是sudo命令(见下文)的配置文件。

【语法格式】

visudo [option]
visudo [选项]

【选项说明】

表14-16针对visudo命令的参数选项进行了说明。

表14-16 visudo命令的参数选项及说明

b14-16.png

14.13.2 visudo命令范例

范例14-22: 执行visudo对普通用户neteagle和younggirl授权的例子。

执行如下visudo命令,即可打开sudo的配置文件进行编辑:

[root@centos7 ~]# visudo    #相当于直接执行vim /etc/sudoers编辑,但使用命令方式更安全,推荐此种方式。

在/etc/sudoers文件的大约第100行下面添加需要提升为root权限的普通用户名及对应权限,格式如下:

neteagle        ALL=(ALL)       ALL
  #此行是第100行,将neteagle提权为root身份。
younggirl ALL=(ALL) /usr/sbin/useradd,/usr/sbin/userdel
#授权younggirl使其可以以root身份添加和删除用户权限。
#分别对neteagle和younggirl两个用户做不同的授权,如上。
:wq

其中,visudo或者vim /etc/sudoers,可在100行下面加入,也可以在其他位置加入。

上述授权内容对应的说明见表14-17。

表14-17 sudo提权配置说明

待授权的用户或组 机器=(授权角色) 可以执行的命令 user MACHINE= COMMANDS neteagle ALL=(ALL) /usr/sbin/useradd,/usr/sbin/userdel

提示: 如果younggirl用户被授予上述权限,那么它可以在所有的机器上以所有的角色运行useradd、userdel命令,而neteagle用户则会拥有与root相同的权限,并且可以切换到root账户。

如果是针对用户组,则对应的授权命令如下:

%用户组 机器=(授权使用哪个角色的权限) /usr/sbin/useradd

通过sudo命令进行系统的授权管理的目的是,既能让运维人员正常工作,又不会威胁到系统的安全,还可以审计用户使用sudo的提权操作命令,默认的用户时无法获取root权限的。、

为了管理方便,工作中可以为neteagle授权ALL权限,neteagle既可管理整个系统,平时也可以使用neteagle用户处理工作,而不使用root用户。

范例14-23: 检查sudoers文件语法的例子。

有的时候,用户并不是使用visudo(保存时会自动检查语法)编辑的sudoers文件,而是使用vim或者echo等命令编辑的sudoers文件,此时就需要执行如下命令检查编辑文件的语法是否正确,如果语法不正确,则可能会导致授权无法生效的问题。

例如,工作中若有批量管理用户的需求,那么使用快速操作命令增加sudo授权,就 需要单独执行语法检查,快速操作命令如下:

[root@centos7 ~]# \cp /etc/sudoers /etc/sudoers.ori
[root@centos7 ~]# echo "neteagle ALL=(ALL) NOPASSWD: ALL" >>/etc/sudoers
[root@centos7 ~]# tail -1 /etc/sudoers
neteagle ALL=(ALL) NOPASSWD: ALL

上述操作是直接追加内容到sudoers文件,并没有进行语法检查,因此需要单独执行语法检查命令:

[root@centos7 ~]# visudo -c #使用-c选项进行语法检查。
/etc/sudoers: parsed OK

关于visudo的更多相关知识,请参考sudo命令一节。

14.14 以另一个用户身份执行命令:sudo

14.14.1 sudo命令介绍

sudo命令可以让普通用户在执行指定的命令或程序时,拥有超级用户(也可以是其他用户)的权限,并且可以有针对性地(精细)将不同命令或程序授予指定的普通用户,同时普通用户不需要知道root密码就可以得到授权,这个授权可以使用visudo配置管理。

【语法格式】

sudo [option]
sudo [选项]

【选项说明】

表14-18针对sudo命令的参数选项进行了说明。

表14-18 sudo命令的参数选项及说明

b14-18.png

14.14.2 sudo命令范例

范例14-24: 查看用户被visudo授权后拥有的权限。

在14.14.1节,我们已经对neteagle用户进行了授权,此时再以neteagle用户的身份登录系统,就可以通过执行类似于sudo ls -l /root(sudo后面加上正常命令)的命令来以root用户的权限管理系统了,命令如下:

[neteagle@centos7 ~]$ ls /root
ls: cannot open directory /root: Permission denied  #可以看到,neteagle用户是无法直接访问/root家目录的。
[neteagle@centos7 ~]$ sudo ls /root #如果授权配置中含有NOPASSWD,则执行时不提示密码,否则会要求输入当前用户的密码。
anaconda-ks.cfg 
#通过sudo命令使得neteagle用户具备访问/root目录的权限。

对于上述代码段的说明,具体如下:

  • 通过sudo授权管理后,所有用户执行授权的特殊权限格式为“sudo 命令”。

  • 如果需要切换到root执行相关操作,则可以通过“sudo su -”命令,注意,此命令提示的密码为当前用户的密码,而不是root的密码。

  • 执行“sudo -l”命令可以查看当前用户被授予的sudo权限集合。

    以下是查看younggirl用户授权的结果情况:

    [C:~]$ ssh [email protected]
    ​
    ​
    Connecting to 10.0.0.201:22...
    Connection established.
    To escape to local shell, press 'Ctrl+Alt+]'.
    ​
    WARNING! The remote SSH server rejected X11 forwarding request.
    Last login: Sun Oct 18 14:58:13 2020
    Wellcome to Linux!
    [younggirl@centos7 ~]$ sudo -l  #注意,这里是younggirl用户,授权较低。
    ​
    We trust you have received the usual lecture from the local System
    Administrator. It usually boils down to these three things:
    ​
        #1) Respect the privacy of others.
        #2) Think before you type.
        #3) With great power comes great responsibility.
    ​
    [sudo] password for younggirl:  #提示输入密码,注意是younggirl用户的密码,而非root密码。
    Matching Defaults entries for younggirl on centos7:
        !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME
        HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE
        LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE",
        env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/sbin:/bin:/usr/sbin:/usr/bin
    ​
    User younggirl may run the following commands on centos7:
        (ALL) /usr/sbin/useradd, /usr/sbin/userdel
    #查看到younggirl用户被授权的权限。
    
  • 对于Linux系统bash的内置命令,一般无法进行sudo授权,例如,cd命令。

    sudo授权与su切换的原理示意图如图14-1所示。

t14-1.png

  • 图14-1 su与sudo用户角色切换原理图

生产环境中通常会禁止root远程登录,不过,系统会为每个运维人员建立一个普通账户,然后根据运维人员的要求,通过sudo控制登录系统的权限,事实证明这是一个不错的权限管理方式。当然,笔者在生产环境中还使用了ldap统一认证登录及授权管理的方式。即只要一个账号和密码,即可在全公司多个机房系统内通行无阻(系统登录、SYN、VPN等),有关这部分内容的讲解,在老男孩教育的高级课程中会有设计。在此,大家了解下即可。

普通用户的环境变量问题:在早期的CentOS 5系统中,普通用户在执行系统管理相关的命令时会遭遇到环境变量的问题,导致找不到执行的命令(CentOS 6以后的系统已经不存在这个问题了)。

sudo授权对于bash的内置命令处理是个难题,因为内置命令没有实体文件和路径,不过一般都有解决方法,例如可以使用sudo ls替代sudo cd,有的网友使用sudo bash后再使用内置命令,这与做是很危险的,不推荐使用这种方法。

14.14.3 sudo扩展知识

如果14-2所示的是sudo的工作原理流程图。

t14-2.png

图14-2 sudo的工作原理流程图(学员绘制)

【时间戳文件位置】

以下命令可用查看CentOS 5.8的时间戳文件位置:

[root@centos5 ~]# ll /var/run/sudo
total 0
drwx------. 2 root neteagle 4096 8-25 12:21 neteagle

要想查看CentOS 6的时间戳文件位置,则要使用如下命令:

[root@centos6 ~]# ll /var/db/sudo
total 4
drwx------ 2 root neteagle 4096 Feb 10 10:35 neteagle   #初始状态是没有这个文件。

若要查看CentOS 7的时间戳文件位置,则要使用如下命令:

[root@centos7 ~]# ll /var/run/sudo
total 0
drwx------. 2 root root 60 Oct 18 17:56 ts

待用户执行sudo并且输入密码后,用户会获得一张默认存活期为5分钟的“入场券”(默认值可以在编译的时候改变)。但超时以后,用户就必须重新输入密码了。

可以使用sudo的-k或-K参数清空sudo用户的时间戳,这样还会提示输入密码,但是如果配置授权对应的用户时加入了NOPASSWD选项,那么执行sudo命令时就永久不会提示输入密码了。

【sudo的配置文件/etc/sudoers】

以下命令可用于查看sudo的配置文件/etc/sudoers里的内容:

[root@centos7 ~]# ll /etc/sudoers
-r--r-----. 1 root root 4441 Oct 18 17:40 /etc/sudoers

建议使用visudo编辑这个文件,因为该命令带有语法检查,否则一旦出错了,普通用户就会无法使用sudo了。直接在命令行执行visudo即可自动打开/etc/sudoers文件。

如果是通过vim编辑/etc/sudoers,则在保存时要使用"wq!"强制保存,否则会提示只读不能保存的错误,而且最后还要用visudo -c做语法检查,这与做实在是太麻烦了,无特殊要求时建议都使用visudo编辑sudo的配置文件。

14.15 CentOS 7系统找回root密码的方法精讲

1)重新启动或开启CentOS 7系统,再选择进入系统的Grub菜单界面,如图14-3所示,根据提示按“e”小写字母进入编辑界面,如图14-14所示。

2)然后,按向下方向键(否则可能会看不到想要查找的行),找到以字符串“Linux16”开头的行,将广播移动到该行的结尾,然后输入“init=/bin/bash”,如图14-4所示。

t14-3.png

图14-3 CentOS 7系统Grub菜单界面

t14-4.png

图14-4 CentOS 7系统Grub菜单进入编辑界面配置图

说明:

如果不确定系统是否开启了SELinux,或者刚装完还没有修改过的系统,则最好使用下面的方法来解决,即在以字符串“Linux16”开头的行,将逛遍移动到该行的结尾,然后输入“init=/bin/bash enforcing=0”(前者的作用是让系统登录后加载bash解释器,后者的作用是关闭SELinux),如图14-5所示。

t14-5.png

图14-5 CentOS 7系统Grub菜单编辑界面增加关闭SELinux配置图

3)配置完成后,根据界面下面的英文提示按Ctrl+x组合键以单用户模式启动Linux,如图14-6所示。

t14-6.png

图14-6 单用户模式界面重新挂载修改密码图界面

说明:

  • 图14-6中的“mount -o rw,remount /”命令用于重新挂载根目录为可写状态(rw表示可写,remount表示重新挂载),在单用户模式下默认根文件系统是出于只读状态。
  • 也可以在增加内核参数时,将以字符串“Linux16”开头的行中间部分的ro参数改为rw,以替代繁琐的“mount -o rw,remount /”命令,具体修改方法如图4-17所示。

t14-7.png

图14-7 修改内核参数ro为rw配置图

4)配置完成后,执行exec /sbin/init命令重启系统,注意,此时,无法使用其他重启命令。特殊强调:如果是系统的SELinux出于开启状态,并且前文修改内核选项时,没有增加“enforcing=0”选项,则此处需要多执行一条“touch /.autorelabel”命令以便在下次系统引导前重新标记系统中所有相关文件(如图14-8所示),因为在开启SELinux时,若在修改root密码时修改password文件则会导致SELinux安全上下文报错,如果前文在修改内核选项时,已增加“enforcing=0”选项,那么,在修改密码文件时,SELinux是处于关闭状态的,因此,这里就不需要执行“touch /.autorelabel”命令了。

t14-8.png

图14-8 处理SELinux以及重启系统界面

5)重启系统后验证修改后的密码是否能够登录,若出现如图14-9所示的界面,则表示密码修改并登录成功。

t14-9.png

图14-9 密码修改并登录成功界面