用户与权限管理#

Linux系统也是一个多用户操作系统 [1]。在多人使用的场景下,就有可能出现权限问题:如一个文件只允许某个用户查看,另一个用户不允许查看;系统设置只允许管理员进行操作,其它用户不允许操作等等。

用户与用户组#

用户与用户组的管理是Linux系统管理的核心任务之一,Linux系统上有大量不同的用户与用户组,而系统内的程序也是以某个用户的身份运行的,所以用户管理相关工作不止止是管理“人”的账户。

用户与用户组的概念#

我们先在系统上创建一个文件,以此为支点了解Linux系统上的用户与用户组是什么样的:

touch test_file
ls -l
../_images/2-24.png

touch 命令是用来更新文件的创建时间、修改时间等信息的,此处被用来创建一个空的文件。ls -l 列出了文件的详细内容(可通过 ls --help 查询ls命令的所有参数),通过这些内容来了解Linux系统的用户和用户组概念。

ls -l 依次列出了以下内容(以test_file为例):

  • -rw-r--r--.:一共10位字符,第一位表示文件类型, - 表示普通文件;后九位每三位为一组,第一组为用户权限,第二组为用户组权限,第三组为其它用户权限,rwx分别表示读、写和执行权限。 . 表示文件受SELinux控制。

  • 1 root root   0硬链接 数量、用户名、用户组名及文件大小。

  • Dec  4 14:49 test_file:文件修改时间和文件名。

ls -l 的更多信息可参考 官方文档

通过 test_file 文件创建,可以了解到,Linux的用户权限有三个类别,分别是属主(owner)、属组(group owner)和其它用户(other users);使用权限也有三个,分别是读(r/read)、写(w/write)和执行(x/execute);还有一个额外的安全控制权限(security context) SELinux。它们共同构成了Linux系统权限控制。

而用户和用户组都拥有系统中唯一标识的ID,分别是UID(user ID)和GID(group ID)。执行 id 命令可以查看当前用户和用户所在的用户组:

../_images/2-25.png

context是SELinux的标识。

一个组内可以有多个用户,如果一个文件的属组权限是该组,该组内的用户则共享读、写和执行权限。

以上概念或许苍白无力,一时难以理解,不要紧的,随着对Linux系统的深入,这些概念之后会自然理解。

保留用户与用户组的配置修改#

系统为系统用户和组保留了1000以下的ID,这些保留的ID可以通过下面的命令查看:

cat /usr/share/doc/setup/uidgid

因此新用户与用户组的创建在分配ID时,会从1000开始。红帽推荐ID分配从5000开始,可以通过修改 /etc/login.defs 来达成此目的:

  1. 使用nano打开这个配置文件:nano /etc/login.defs

  2. 按键盘中的方向键的↓键,找到UID_MIN的配置:

# Min/max values for automatic uid selection in useradd(8)
#
UID_MIN                  1000
  1. 将UID_MIN的值更改为5000

# Min/max values for automatic uid selection in useradd(8)
#
UID_MIN                  5000
  1. 继续按↓键打到GID_MIN的配置

# Min/max values for automatic gid selection in groupadd(8)
#
GID_MIN                  1000
  1. 将GID_MIN的值更改为5000

# Min/max values for automatic gid selection in groupadd(8)
#
GID_MIN                  5000
  1. 按下Ctrl+X键退出编辑,输入Y保存修改,然后按下回车键保存到文件中

之后在新建用户与用户组时,系统会为它们分配5000之后的ID

警告

/etc/login.defs 中的其它配置项在不理解的情况下不要随意修改,该文件是系统配置文件,随意修改可能会导致系统产生意外问题。

用户私有组#

在组管理上,系统使用了一种叫用户私有组(user private group,UPG)的配置:即在某个用户创建时,会同时创建一个与该用户名同名的组名,这个组内只有该用户。如使用 id 查看当前登录的用户与组信息时,可以看到用户名和组名都是 root

UPG的配置会让权限管理更方便更安全:某个用户创建了一个文件,UPG会设定好一个默认权限(如上面的test_file的例子),该用户与组内用户都可以访问修改这个文件,其它用户无法访问修改;另一个用户如果想访问修改这个文件,直接把他加入到此用户组中即可。

系统上所有的用户组可通过 cat /etc/group 查看。

备注

系统运行时,有很多系统服务也在后台同时运行,因此通过 cat /etc/group 查看系统上的用户组时,会有很多用户组,而我们从未创建过它们,这些用户组是在操作系统安装过程中创建的且由系统服务使用。

用户账号及用户组的权限管理#

用户账号分为以下类型:

  • 普通用户(Normal user accounts)

    可以被创建,修改和删除的常规账号

  • 系统用户(System user accounts)

    系统用户在系统上对应着一个系统服务,这类用户只有在软件安装时创建,之后不会进行修改。

    系统用户的UID为1000以下,常规用户的UID从1000开始,不过我们通过 /etc/login.defs 修改为从5000开始,这也是红帽推荐的配置修改。

警告

系统用户一般只配置本机可用,不允许远程登录,否则可能会导致系统服务出问题。

  • 组(group)

    组是多个用户集合在一起的单元,用来达到某些特殊目的。比如将一个文件的读写权限赋予给某个组,那这个组内的所有用户都可以对这个文件进行读写。

通过命令行创建用户#

创建一个test用户并为其设置密码:

  • 创建test用户

    useradd test
    
  • 查看创建好的test用户

    id test
    

    该用户是系统上第一个创建的常规用户,它的uid及gid都应该是5000。

  • 为test的用户设置密码

    passwd test
    

    passwd会提示输入两次密码,这两次密码要保持一致,当提示 passwd: all authentication tokens updated successfully. ,说明为test用户设置密码的操作已成功。

  • 登录新创建的test用户

    可以在vmware中直接登录刚刚创建好的test用户,如果此前已登录了系统,可先执行 exit 命令退出。

    ../_images/2-26.png

以上便是创建新用户test的过程,是不是非常简单?

创建用户组#

创建一个用户组:

  • 创建group_test用户组:

    groupadd group_test
    
  • 确认group_test用户组创建结果:

    tail /etc/group
    
../_images/2-27.png

提示

通过 man groupadd 了解groupadd的更多信息

通过 man tail 了解tail的更多信息

为用户添加附加组#

将用户添加到附加组中可以管理用户的访问权限

  • 将test用户添加到group_test用户组中:

    usermod --append -G group_test test
    
  • 确认test用户已加入到group_test组中:

    groups test
    

提示

通过 man usermodman groups 了解它们的作用

创建group_test的文件夹#

前面我们提到,文件有 -rw-r--r-- 十位权限字符,从第二个开始,每三位为一组,分别分别表示用户、用户组、其它用户这三种权限。在UPG系统的配置下,通过设置用户组权限(setgid: set-group identification permission )来实现多用户对某个文件夹的权限控制,将这个文件夹授权给别个用户组,同属于这个用户组的多个用户都可以这个访问这个特定的文件夹,文件夹内的文件也将继承这些权限。

接下来我们将实现这个功能

  • 创建文件夹

    mkdir /opt/share_dir
    # 查看创建好的文件夹
    ls -dl /opt/share_dir
    
  • 将创建好的group_test组与这个文件夹关联

    chgrp group_test /opt/share_dir/
    # 再次查看创建好的文件夹,比对之前的权限区别
    ls -dl /opt/share_dir
    
  • 为组用户组设置权限以setgid,同时移除其它用户的权限

    chmod g+rwxs,o-rx /opt/share_dir/
    # 查看权限变化
    ls -dl /opt/share_dir
    

对比 /opt/share_dir 最初的权限和最新的权限变化:

../_images/2-28.png

提示

# 开头的内容为注释说明文字,命令行不会执行相关内容。

mkdir是用来创建文件夹的命令,意为“make directories”。

ls命令中的d参数是用来列出文件夹的信息,ls默认只列出文件。

chgrp是改变文件属组的命令,意为“change group ownership”。

chmod是改变文件权限的命令,参数说明如下:

  • +号用来增加权限,-号用来取消权限

  • u表示user,g表示group,o表示other users,a表示all users

  • r表示read,w表示write,x表示execute(无此权限无法进入文件夹),s用于设置用户或用户组的权限(set user or group ID on execution,setuid or setgit),如文件夹内的文件在创建时会自动为该文件设置属主(setuid)或属组(setgit)权限。 还有一个特殊的权限t,表示sticky bit,用于文件夹的权限,当设置了sticky bit权限后,只有文件的属主和root用户才可以删除该文件,其它用户无法删除该文件。

  • 权限也可用数字来表示,read(4)write(2)execute(1)来分别表示,如用户权限是读和执行,则权限为5(读和执行相加)。可以一次设置用户、用户组和其它用户三组权限,如 chmod u+rwx,g+rwx /opt/share_dir 可写作chmod 770 /opt/share_dir,每一个数字代表一组权限。

以上命令可通过 man chmod 命令来了解学习更多内容,该命令较为复杂,后续章节将继续介绍更多细节,此处只做简单理解即可。

验证share_dir的权限是否生效#

作为对比,我们再创建一个用户,这个用户不加入 group_test 用户组来访问 share_dir 文件夹。

# 添加用户test1
useradd test1
# 为用户test1设置密码
passwd test1

xshell可以复制当前会话,这样我们就可以有两个窗口来进行测试,双击会话选项页标题(下图红色部分)即可:

../_images/2-29.png

在其中一个窗口执行 su - test ,另一个窗口执行 su - test1 ,这样就相当于登录了这两个测试用户:

../_images/2-30.png

此时,两个用户都执行 cd /opt/share_dir ,看结果如何:

../_images/2-31.png

提示

@ 前为用户名,后为主机名,因此在执行su命令后, @ 前的用户名变了。

su命令用来以另一个用户的身份执行命令,此处可以用来切换用户,通过 man su 了解多更信息。

cd命令用来跳转文件夹,意为“Change directory”。

可以看到 test1 用户因为不在 group_test 的用户组中,在访问属于 group_test 的文件夹时,提示 Permission denied ,也就是没有权限(此处测试x权限)。

两个用户都执行创建文件的命令 touch /opt/share_dir/test_file,看结果如何(此处测试w权限):

../_images/2-32.png

两个用户都执行 cat /opt/share_dir/test_file ,看结果如何(此处测试r权限):

../_images/2-33.png

可以看到,在其它用户权限为 --- 时,test1用户没有任何访问 /opt/share_dir 的权限,这就是UPG系统的作用,用户可以通过加入特别的用户组中,获得特别的权限。同时,因为设置了setgid,test_file也会继承 group_test 组的权限。

重要

在各个窗口中执行 exit 可以切回到root用户,后续的内容均需要root用户来操作。通过 su 命令切换到某个用户进行测试后,记得及时切回到root用户。

root 用户是超级管理员,是linux系统上权限最大的用户,它可以执行任何操作,而普通用户则受到权限限制,不能执行管理命令,如 useraddusermod 等。

用户组的修改#

同属于一个用户组的用户,拥有相同的文件和文件夹的访问权限,因此修改用户组可以用来改变用户的权限。

主要用户组和附加用户组#

用户组是由多个用户组成,为了共同的管理目的而组成的单元,如授权访问一个特定文件。

在Linux系统中,用户组主要分为两种:主要用户组(primary group)和附加用户组(Supplementary group)。它们有如下属性:

主要用户组

  • 所有用户有且只有一个主要用户组。

  • 主要用户组可以被修改。

附加用户组

  • 多个用户可以被同时添加到一个附加用户组中,这些用户出于相同的访问权限控制目的。

  • 附加用户组的成员数量可以为0;一个用户也可以同时属于多个附加用户组。

查看主要用户组和附加用户组#

主要用户组和附加用户组都可以通过 groups 来查看:

  • 如查看test用户的主要用户组与附加用户组的情况:

    groups test
    

    提示

    输出结果为 test : test group_test ,第一个test就是主要用户组,而 group_test 则是附加用户组,无论输出多少用户组,第一个永远是该用户的主要用户组,后面的都是附加用户组。

  • 如查看test1的用户组情况:

    groups test1
    

    因为test1用户并没有加入任何其它用户组中,因此它只输出 test1 这一个主要用户组。

如果 groups 命令不加任何参数,它则会输出当前登录用户的主要用户组和附加用户组,当前用户就是 @ 符号前显示的名字。

更改用户的主要用户组#

将用户的主要用户组修改到另一个已存在的用户组中,可以通过 usermod 命令来实现:

# 将test1用户的主要用户组修改为test
usermod -g test test1

修改完成后,用户的家目录的用户组属主也会随之更新:

../_images/2-34.png

将用户添加到附加用户组中#

将用户添加到附加用户组中,可以管理用户的访问权限,如上面的 /opt/share_dir 文件夹,只有属于 group_test 用户组的用户才能访问。

所以test用户可以访问,而test1用户不能访问,将test1用户添加到 group_test 用户组中,以便让test1用户也可以访问 /opt/share_dir 文件夹。

usermod -a -G group_test test1

此时,通过 su - test1 切换到test1用户,再次通过 cd /opt/share_dir 访问该文件夹,看是否可以访问。

将用户从附加用户组中删除#

将用户从附加用户组中删除,可以撤销用户的访问权限,如刚刚加入 group_test 用户组的test1用户,将它从 group_test 用户组中删除,它就不能再访问 /opt/share_dir 了。

gpasswd -d test1 group_test
# 查看test1的用户组信息,此时它已不属于group_test用户组
groups test1

test1此时已无访问 /opt/share_dir 的权限:

../_images/2-35.png

提示

gpasswd命令是用来管理用户组的命令,通过 man gpasswd 了解更多信息。

更改用户的所有附加组#

用户可以属于多个不用的用户组,这些用户组可以一次性修改完成。

一性次为test1用户添加多个附加用户组,每个用户组用逗号隔开:

usermod -G test1,group_test,wheel test1

查看test1用户的用户组信息:

groups test1

此时,test1用户已经有 wheel group_test test1 三个附加用户组了。

usermod在统一增加附加用户组时,未被提及的用户组将被删除:

# 去掉wheel,usermod将会删除wheel用户组,保留test1和group_test用户组
usermod -G test1,group_test test1

利用这个特性,usermod可以更方便的管理用户的多个附加组,以此来更灵活的管理用户权限。

更改及重置root密码#

root用户是Linux系统中权限最大的用户,它的密码安全性十分重要,更改和重置root密码也是系统管理的重要任务之一。

提示

为防止误操作,导致安装好的系统无法使用,在操作前通过vmware的快照功能,创建一个快照,以便在操作失误时恢复到操作前的状态。

更改root密码#

更改root密码,可以直接通过 passwd 来实现,注意当前执行命令的用户为root:

passwd

根据命令提示,输入两次相同的密码,即可更改成功。

passwd 还有一个非常有用的参数,可以一行命令完成密码的更改:

echo "new_password" | passwd --stdin root

提示

echo和passwd是两个命令,上述命令是将echo的输出结果给到passwd命令作为它的输入;中间的 | 被称为管道符,它可以将两个命令结合起来,将前一个命令的输出作为后一个命令的输入。

执行完这行命令后,root密码就直接改为 new_password 了,不需要输入两次密码,将 root 换成其它用户名,如 test ,也可以直接更改对应的用户密码。

非root用户身份下更改root密码#

假使root密码忘记了,这时候系统上其它的管理用户还可以正常登录,则可以通过这些管理用户来更改或重置root密码。

之前建的 testtest1 用户都是普通用户,它们连 usermod 这种管理命令都无法执行,因此需要把其中一个用户提升为管理用户,以便本小节的实验继续进行。

系统上有一个特殊的用户组 wheel ,这个用户组就是管理员用户组,任何用户只要加入到这个用户组中,摇身一变就成了管理员了。接下来我们将 test 用户加入到 wheel 用户组中,使之成为管理员。

usermod -a -G wheel test

此时 test 用户已经成为管理员了,恰巧root密码忘记了,无法登录,这时便可以通过 test 用户来为root用户重置密码。

# 假使root用户忘记密码无法登录,su模拟test用户登录系统
su - test
# sudo命令的作用是以其它用户的身份执行命令,此处是以root用户的身份执行passwd命令
sudo passwd root
../_images/2-36.png

这里提示首先输入一次test用户的密码,然后再输入两次密码便可为root用户重置密码。

提示

虽然 test 是管理员用户,但执行某些管理命令(如 passwd)时,还是需要通过 sudo 命令以 root 身份来执行,这是和windows系统管理员不同的地方。

boot 中重置root密码#

在假设一种极端情况,root密码忘记了无法登录,其它管理员用户也无法登录,系统中又有重要数据,不能通过重装系统来恢复,怎么办?

这时候就可以通过 boot 进入一个特殊环境 chroot jail 中进行root密码的重置: 简单来讲,按下电源键(vmware中是按下虚拟机中的启动按钮)到系统启动完成这一过程,称之为 boot ,正常情况下它会进入正常的操作系统环境中,只不过我们在 boot 过程中人工介入,让它进入一个 chroot jail 的环境中,用来重置root密码。

重要

此小节操作稍有误,极易导致安装好的虚拟机系统无法使用,操作前请先创建一个快照,以便在操作失误时,恢复到失误前的正常状态。

  1. 打开vmware,停留在操作界面,在xshell中在root用户下执行 reboot 命令,使系统重启,同时盯紧vmware界面,如下图:

    ../_images/2-37.png
  2. 当虚拟机屏幕出现以下图像时,迅速用鼠标左右点击屏幕,同时按下键盘上的 E 键:

    ../_images/2-38.png
  3. 如上述步骤操作成功,你将进入内核启动参数(kernel boot parameters)界面:

    ../_images/2-39.png
  4. 按键盘上的方向键,可以上下左右移动光标,将光标移动到以 linux 开头的行上:

    ../_images/2-40.png

    按下[Ctrl+E]键,光标将移动到行尾,在此处输入 rd.break ,注意前面有空格:

    ../_images/2-41.png

    提示

    linux 开头的行尾是 \ ,其实它与下一行是连在一起的,被当作一行处理,所以当按下[Ctrl+E]键(该快捷键的作用是将光标移动到行尾)后,光标会移动到 /swap 处,也就是说 linxu/swap 这三行其实是一行,而 \ 是将这一行在屏幕中分割成了三行而已。

  5. 按下[Ctrl+X]键,系统将以更改后的内核启动参数启动系统,启动完成后将出现 switch_root 的提示:

    ../_images/2-42.png
  6. 此时系统是只读模式,挂载在 /sysroot 目录上,无法更改密码,还需要重新挂载一下,使系统进入可写的模式:

    mount -o remount,rw /sysroot
    
  7. 执行以下命令,重置root密码:

    # 进入chroot环境
    chroot /sysroot
    # 重置root密码
    passwd
    # 让SELinux在下次启动时重新打标签
    touch /.autorelabel
    # 退出chroot环境
    exit
    # 退出switch_root
    exit
    
    ../_images/2-43.png

    此时SELinux将会启动打标签的进程,当这个进程完成后,系统将会自动重启,重启后就可以使用新密码登录系统了。

提示

mount命令是用来挂载文件系统的命令,后续在文件系统管理中还会涉及。

chroot命令是用来更改根目录的命令,通过它可以进入一个特殊的环境,用来执行root密码重置等操作。

根目录是Linux系统中的最顶层目录,所有的文件和文件夹都是从根目录开始的。如/opt/share_dir/ 就是根目录。而 chroot 命令将根目录更改为/sysroot ,这样 /sysroot 就成了根目录,所有的操作都是基于 /sysroot 的。

脚注