封面来源:https://www.ninjaone.com/wp-content/uploads/2024/03/N1-0921-Linux-Administration-and-User-Management-blog-image-1.png

引言

对于每一位专业或是业余的 Linux 运维而言,权限控制这件事,真的不能掉以轻心。毕竟 Linux 的设计哲学就是“一切皆文件”,一不小心,手滑删了系统关键文件,或者误改了引导配置,那可能就直接“从删库到跑路了”有些 CMS 像 WordPress 和 Typecho 还真就是用 PHP 写的

有些小伙伴可能会想到把重要文件备份到外接硬盘,或者干脆在服务器上搭建一个类似于 NextCloud 的云存储服务,再加个密码保护。这方法确实可行,但操作起来不是麻烦就是有点门槛,并且也不是每个人都愿意折腾。

那有没有更省心、更一劳永逸的办法呢?有的 xd,有的。这就是我们今天要讲的 Linux 两大特色——用户权限控制

用户账户

和 Windows 不同,在 Linux 中,用户账户主要分为三种类型:root系统账户普通用户

root

root,也称为超级用户根用户,拥有系统中至高无上的权限。它可以不受任何限制地执行任何操作(严格的说,是在内核层面操作),包括但不限于:

  • 安装、更新或删除系统级软件

  • 修改系统核心配置文件和启动项

  • 挂载或卸载文件系统

  • 管理所有用户的账户和权限

  • 访问和修改系统上的任何文件,包括那些属于其他用户的私有文件(但是有些软件光盘不行)

root 就像一把双刃剑,搞得不好很容易出岔子,轻则应用崩溃,重则系统无法启动甚至报废。

下面是一个滥用 root 权限的经典案例(虽然不是 root 用户):

可以看到,系统已经无法启动,选择 Hard Drive 一项没有任何反应。

因此,在使用 root 用户时,需要非常谨慎。当然,在某些安装程序(如常用的 Calameres)内,root 用户可以被设置为禁用。

普通用户

普通用户是我们在日常工作中主要使用的账户类型。他们的权限被严格限制在自己的主目录(/home/username)内,不能直接修改系统级的设置或访问其他用户的私有文件,从而有效阻止了未经授权的访问和对系统的潜在危害。

但是!普通用户可以通过加入特定的管理组(如早期和 Fedora 系的 wheel 组或 Debian 系中的 sudo 组)来获得临时提升权限的能力。这意味着,在得到授权的情况下(此时需要密码),他们可以在命令前加上 sudo 来执行需要 root 权限的操作,系统会验证其密码后临时赋予其超级用户权限。

系统用户

系统用户(或称为服务账户)是一类比较特殊的用户,它们通常是在安装软件或服务时由系统自动创建的。这些用户的主要目的不是为了让人来登录,而是为了运行特定的后台进程(daemon)、服务或守护进程

系统用户通常具有以下特点:

  • 没有标准的登录 Shell(其 Shell 通常被设置为 /usr/sbin/nologin/bin/false),因此无法像普通用户一样通过终端登录。

  • 通常没有设置可用的登录密码

  • 拥有一个特定的、受限的权限范围,仅能访问与其所属服务相关的文件和目录。

这样一来,即使某个服务被攻击者利用,其破坏也会被限制在该用户的权限范围内,而不会危及整个系统。

组(别名“用户组”和“工作组”)在 Linux 内是另一个非常重要的概念。和 Windows 类似,Linux 也采用用户组的方式来批量管理用户权限。

一般我们在安装系统时,如果 root 用户可以被禁用,安装程序通常都会要求创建一个管理员用户:

此时系统就会在以该用户名创建新用户组的同时,将该用户加入到 wheel 组或 sudo 组内,但如果仅仅是一位普通用户,则不会进行后面的步骤。此时,我们称前者(用户名组)为主要组,后者(如 wheelsudo)为附加组

用户在加入新组后,会继承该组内所有的权限。我们可以举一个例子:

我这个站点用的是 Halo 建设的,而 Halo 分为免费开源的社区版和付费的 Pro 版。Pro 版的某些功能、插件和主题等在社区版是不可用的,我们称之为专有资源。当我们购买 Pro 版时,无论选择年付还是买断,我们都能够使用那些专有的资源,而当年付的 Pro 版本到期时,这些专有的资源也就不可用了。一般系统会为购买了 Pro 版的用户(不管是年付还是买断)授予 Pro 版本专有资源的访问和使用权限(实际上不一定是这种技术实现,这里只是做个类比!),但是这些用户的基数是很大的,要是一个个给用户授予权限,那不还得忙到猴年马月了?因此,一种更快并且更安全的方式是将这些用户加入到相关特权组内,如果用户的 Pro 版本到期了,就将该用户移除。

创建、更改或删除用户和组

这部分内容比较多,我们一个个来。

创建新用户

创建新用户有两种方式:adduseruseradd. 但对于不同的发行版,二者的作用可能互不相同。

在基于 Debian/Ubuntu 的发行版上,adduser 实际上是使用了一个 Perl 脚本(管他怎么写的,用就是了)执行 useradd 命令,可以一步步引导管理员设置用户名、密码、主目录和终端等信息。而 useradd 命令则是一个低等级的命令,不同于 adduser它不会主动提示你添加用户目录等信息,只会创建一个用户空壳。

而在基于 Fedora/RHEL 的发行版上,adduser 仅仅是 useradd 的软链接,两者是完全等同的命令,调用哪一个效果都一样。因此,在这些发行版中,通常直接使用 useradd 命令,其行为模式与 Debian/Ubuntu 下的 useradd 一致,默认不会创建主目录,也不会进行交互式提示,需要管理员通过命令行参数明确指定所有配置。

这里,我们以 Fedora/RHEL 系的发行版(wheel 组内成员拥有管理员权限)为例,简要说明如何快速创建一个新用户。

创建一个基本用户

下面是一个最基本的命令,它会创建一个名为“raccoon”的新用户,但不会创建主目录也不会设置有效的登录 Shell

useradd raccoon # Replace "raccoon" with your custom username

该用户很像之前提到的系统用户,权限非常有限,不可登录

创建完整且可以登录的普通用户

useradd -m -s /bin/bash raccoon
# You can use other shells like zsh or fish as well

其中,-m 参数告诉系统为该用户创建主目录(通常在 /home/raccoon),而 -s 会指定用户登录的 Shell 名称(本例中为 bash)。

设置用户密码

这一步是必须要做的,因为后面使用该账户时系统会提示需要输入密码,否则账户会被锁定。

sudo passwd raccoon # sudo is a must

系统会提示并确认你输入的新密码。

请注意,如果 passwd 后没有用户名,将会修改当前用户名(包括 root)的密码。

普通用户在修改密码时,请务必联系管理员。

(可选)指定用户组

在创建用户时,还可以指定用户所在的用户组。这一步可以现在进行,也可以后续再进行修改。

我们可以指定用户的主要组(需要使用 -g 参数,注意大小写敏感):

useradd -m -s /bin/bash -g ubuntults raccoon

这样系统会将用户 raccoon 加入到 ubuntults 组(而不是 raccoon 组)中。

请注意,在指定用户组时,该用户组必须存在

如果想指定附加组,我们需要使用 -G 参数:

useradd -m -s /bin/bash -G wheel,ubuntults raccoon

系统此时除了会创建 raccoon 组,还会将用户 raccoon 加入到 ubuntults 组中,并赋予管理员权限(加入 wheel 组)

更多关于 useradd 的高级用法可以参考:

https://www.runoob.com/linux/linux-comm-useradd.html

更改用户名称、主目录、shell 等

usermod 命令可以用来更改用户名称、主目录、登录的 shell.

要更改用户名称,我们需要使用 -l 参数(注意顺序,先是修改的用户名,然后是原来的用户名):

usermod -l resolute_raccoon raccoon

要更改用户的主目录,我们需要使用 -d 参数:

usermod -d /home/resolute_raccoon resolute_raccoon

要更改用户登录的 shell,我们需要使用 -s 参数:

usermod -s /bin/bash resolute_raccoon

请注意,当登录的 shell 设置为 /sbin/nologin 时,用户即使输入正确的密码, 也无法登录进入系统,此时系统会提示该用户不可登录。这和不指定 shell 是一个作用,它可以防止一些需要使用系统资源的系统账户被人为使用,从而导致系统被破坏。

其他一些比较高级的参数如下(或参阅此处):

参数

含义

-u

修改用户的 UID

-e

设置用户过期时间,格式为 YYYY-MM-DD

-c

为用户添加或修改备注

-f

设置在密码过期多少天后关闭用户

设置用户过期时间

之前提到的参数 -e 可以设置用户的过期时间。用法如下:

usermod -e 2026-04-01 resolute_raccoon # Replace them with your date-time and username

这样会使用户 resolute_raccoon 在 2026 年 4 月 1 日过期(有效期至 2026 年 3 月 31 日),随后不可再登录该用户。这非常适合测试或临时性使用的情况。

请注意,时间格式必须为 YYYY-MM-DD包括前导 0),否则不会生效。

查看用户的状态

我们可以使用 chage 命令(参考)来检查用户的状态。例如:

chage -l resolute_raccoon

这会显示该用户的密码过期和失效时间,以及之前我们设定的账户过期时间。

修改用户所在的群组

这里有两种情况:覆盖修改和追加修改。

覆盖修改会替换用户的主要组或附加组。修改主要组时,单独使用 -g 参数,附加组则使用 -G 参数。例如:

usermod -g newdeblts trixie
usermod -G stable,debian trixie # No space is allowed between each supplementary group
# Please make sure that the groups exist

追加修改则不会替换,而是在原有组的基础上将用户加入新的用户组。使用时,只需要在覆盖修改的参数之前,加上 -a 参数。例如:

usermod -a -G debian,linux resolute_raccoon # Add the user to new supplementary groups

删除用户

要删除一位用户,我们需要使用 userdel 命令。

userdel -r resolute_raccoon

该命令会删除名为 resolute_raccoon 的用户和用户组,以及主目录和其中的所有文件。

不使用 -r 参数时,将不会删除用户的主目录和其中的文件

创建新组

使用 groupadd 命令以创建一个新组。

groupadd deblinux

其他一些比较高级的命令如下:

参数/选项

含义

-g

指定新建组的 id

-r

创建系统工作组,且组 ID 小于 500

-K

覆盖配置文件 /etc/login.defs

-o

允许添加组 ID 号不唯一的组。

-f,--force

如果指定的组已经存在,此选项将不会提示错误,仅以成功状态退出。当与 -g 一起使用,并且指定的 GID_MIN 已经存在时,选择另一个唯一的 GID(即 -g 关闭)

查看用户所在的所有组

这个命令非常简单:

groups resolute_raccoon

如果你想查看系统内所有可用的用户组,可以使用下面的命令:

cut -d: -f1 /etc/group

将用户加入和移出该组

要将用户加入某个组,请参阅“修改用户所在的群组”部分,原理相同。

或者,也可以使用 gpasswd 命令用户名在前!!):

sudo gpasswd -a resolute_raccoon deblinux

要将用户移出某个组:

sudo gpasswd -d resolute_raccoon deblinux

更改组名称

类似于 usermod,Linux 也提供了名为 groupmod 的命令。更改组名称需要使用 -n 参数,命令如下:

groupmod -n debianlinux deblinux

删除组

同样,我们可以使用 groupdel 来删除一个组。这个命令也很简单:

groupdel debianlinux

请注意:

  • 如果某个用户的主要组是该组,则无法直接删除。你必须先修改该用户的主要组,或者删除该用户后,才能删除这个组。

  • 删除组之前,请确保没有文件或目录的属组是该组,否则这些文件的所属的组ID(GID)将变为“孤儿”,在系统中显示为不再存在的数字GID。

锁定和解锁用户

锁定一位用户需要使用我们之前介绍的 usermod 命令,以及 -l 参数或 --lock 选项。例如:

usermod -l resolute_raccoon

此时,该用户将无法登录系统,也无法从其他用户切换到该用户或者使用 sudo 命令提权。如果你尝试查看 /etc/shadows 文件并使用 grep resolute_raccoon 找到该用户,你会发现在首个冒号后面开始的内容(也就是用户密码的哈希值)被加上了一个英文感叹号,就像这样:

resolute_raccoon:!$6$abcdefg...

要解锁用户,需要使用 -u 参数或 --unlock 选项(请注意,该命令对于过期或因多次输入密码错误被锁的用户无效):

usermod -u resolute_raccoon

此时即可再次使用该用户。

忘记密码怎么办?

请注意:进行下面的操作时,必须确保系统内有 root 用户,否则会导致修改失败。修改时,请务必小心操作。我们假定系统使用的引导程序是 GRUB2,不是 systemd-boot 或 rEFInd 等其他引导程序。

当你不慎忘记用户密码时,无需惊慌。在绝大多数 Linux 发行版中,最有效的解决方法是通过 GRUB 引导加载器进入单用户模式,从而以最高权限重置密码。我们需要遵循如下步骤:

  1. 在显示 GRUB 菜单时,迅速按 Up 和 Down 键(方向键)取消倒计时,并选择你想启动的内核版本不要按回车!!)。

  2. e 进入编辑模式,找到 “linux” 这一行,使用方向键将光标移动到 ro 的后面。

  3. 删除 ro 后面的内容,将 ro 改为 rw single console=tty init=/bin/bash.

  4. 按 Ctrl + X 或者 F10 引导。

  5. 进入单用户模式,待出现输入 root 密码的提示后,按照提示输入密码继续。

  6. 键入 passwd USERNAME 命令修改密码(请将 USERNAME 改成你自己的用户名),然后使用 exec /sbin/reboot -f 命令(不是 reboot,因为此时系统启动不完全)重启系统。

但是在 Fedora 43 的单用户模式下,passwd 和 id 等很多维护系统所必要的命令显示都不存在,因此只能通过救援模式root 用户重置。此时仅需执行上面第 6 步。

如果没有 GRUB 菜单怎么办?

如果系统开机时没有出现 GRUB 菜单,并且又忘记了密码,请先使用 root 登录修改密码,再编辑 /etc/default/grub文件。

GRUB 菜单缺失的原因有 2 种:

  • GRUB 菜单设定为 hidden,或者该配置项直接缺失。

  • 倒计时设置为 0s.

这样一来,我们需要修改(或增加)下面两个配置项:

GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=5 # Or longer if you wish, e.g. 10

运行下面的命令生成 GRUB 所需的配置文件:

grub-mkconfig -o /boot/grub/grub.cfg
# This would be grub2-mkconfig in Fedora/RHEL

随后重启系统,就能看到 GRUB 菜单了。

下一期的内容?

下一期我们会讲到权限控制的核心——文件与目录的读写执行权限,以及如何用 chmodchown 命令精确掌控它们。

C/C++ 新人开发者,主攻 UE5,业余 Linux 运维