whoami
在这个例子中,我以“dave”用户身份登录,所以这个命令打印出:
dave
现在,将“sudo”添加到同一个命令之前:
sudo whoami
尽管您仍然以非 root 用户身份登录,但由于 sudo,您在单个命令的持续时间内的有效用户 ID 已经改变:

root
让我们看一个更实际的例子,我们想要以 root 身份运行单个操作,但然后继续以我们的常规用户身份运行其他命令:
sudo systemctl start nginx<go back to doing regular-user stuff>
第一个命令启动 nginx Web 服务器(假设已安装 nginx 包),这是只有 root 才能做的事情。之后的任何命令都再次以您的常规用户身份执行。 这是一种常见的工作流程,确保安全——您大部分时间都以常规用户身份工作,无法用单个命令破坏整个系统。当您需要 root 权限时,您通过在需要它们的命令前加上 sudo 来调用它们。这是一个很好的心理屏障,可以防止您不小心破坏系统上的东西。 您将看到这种模式被用于系统上的各种潜在危险事情,例如编辑系统级配置文件、在用户的主目录外创建目录(本章后面介绍)等:
sudo mkdir /var/log/foobarsudo vim /etc/hostssudo mount /dev/sdb1
您可以使用 sudo 获得一个长期的 root shell 会话,如果您计划作为 root 运行许多命令(或者如果您正在排除一个以 root 运行的问题,或者模拟 cloud-init 脚本将执行的环境):
sudo -i
这将为您提供一个作为 root 用户的交互式 shell 会话。小心使用这个!
没有什么可以阻止您用一个错误或一个输入不当的命令破坏系统。 虽然 sudo 默认将当前用户替换为 root 用户,但您也可以通过 –u 选项将其更改为另一个用户。例如:
sudo –u myuser vim /home/myuser/.bashrc
这将以 myuser 用户的身份在 vim 中打开 /home/myuser/.bashrc。 谁(或哪个组)被允许做什么,可以定义在 /etc/sudo.conf 中。您永远不应该直接编辑这个文件;使用 visudo 命令来修改文件。 什么是组? 组是允许一组用户共享权限的另一个基本工具。组通常用于获得权限集或配置文件的功能。例如,在 Linux 上,通常有一个名为 sudoers 的组,在 macOS 上,您会遇到一个名为 wheel 的组。按照惯例,这些系统上属于 sudoers 或 wheel 组的用户被允许使用 sudo 执行命令作为 root。这在功能上与在 Windows 中将用户添加到 Administrators 组相同。 您可以推断,如果组对管理谁被允许运行 sudo 命令很有用,它们也可能对将用户分组和管理其他类型的权限很有用。 迷你项目:用户和组管理 例如,假设我们想要允许公司的每个软件开发人员阅读一个给定的文件——让我们称之为 document.txt。我们可以简单地创建一个开发人员组,并将所有开发人员用户添加到该组中。 然后,当我们为 document.txt 设置所有权和权限时,我们可以引用开发人员组,而不是试图跟踪可能属于该组的每个单独用户的个体。 创建用户 在已安装 adduser 命令的 Linux 系统上,您可以使用它来交互式地创建一个名为 dave 的用户。如果您没有,该包通常名为 useradd(有关安装包的更多详细信息,请参见第 9 章,“管理已安装的软件”)。 使用用户名作为唯一参数运行命令将为您提供一个向导式的用户创建过程。请注意,我们在这里使用 sudo,因为只有 root 可以添加或删除用户:
$ sudo adduser steve
添加用户 steve ... 添加新组 steve (1000) ... 添加新用户 steve (1000) 与组 steve ... 创建主目录 /home/steve ... 从 /etc/skel 复制文件... 新密码:
重新输入新密码:
passwd:密码成功更新 更改 steve 的用户信息 输入新值,或按 ENTER 键使用默认值 全名 []: Steve
房间号码 []: 工作电话 []: 家庭电话 []: 其他 []: 信息正确吗?[Y/n] y 我们加粗了需要我们交互的部分——即,设置密码、全名和确认我们想要在系统上创建此用户的确认。 这是添加一个或两个用户的好方法,但是如果您正在处理一个需要为您的 300 个最大客户分别拥有个人帐户的 Linux 测试服务器呢?您将需要非交互式 useradd 命令,它允许您将用户属性作为参数指定给单个命令。这使得用户更改易于脚本化(请参阅本章后面关于可脚本化的注释):
useradd --home-dir /home/dave --create-home --shell /bin/zsh -g dave -G sudoers dave
该命令还包括:
设置并创建用户的主目录(--home-dir 和 --create-home) 设置自定义 shell(--shell) 将用户的主组设置为 dave(尽管这也可能是员工)使用 -g 选项 将附加组成员身份添加到 sudoers 组(您可以在此处传递多个逗号分隔的组名) 就这样——如果命令成功退出,您的新用户就已经创建了!
但我们还没有完成——这个用户将在新的、最高机密的 tutorialinux 应用程序上工作,所以让我们为该项目创建一个组,并将我们的新用户添加到其中。
创建组 要创建一个名为 tutorialinux 的新组,您将使用 groupadd 命令:
groupadd tutorialinux
这在系统上创建了一个新的组,在 Unix 系统上存在的所有组的记录 /etc/group 配置文件中添加了一行。您可以通过在该文件中“grep”(搜索)组名来验证组是否已创建:
# grep tutorialinux /etc/grouptutorialinux:x:1001:
您可以看到,现在存在一个名为 tutorialinux 的组,组 ID(GID)为 1001。
我们不会深入探讨这里的 x 字符意味着什么;知道这个文件由每组一行组成,以冒号分隔的值就足够了。您将只关心组名(第一列)、组 ID(第三列)和成员(最后一列,在本例中为空)。
修改 Linux 用户 正如 useradd 允许您在用户创建期间随意设置用户元数据一样,usermod 和 gpasswd 允许您修改现有用户的所有方面。让我们将我们之前创建的 dave 用户添加到新的 tutorialinux 组中,这样他就可以处理只有组成员才能看到或修改的项目文件。
将 Linux 用户添加到组 要更改用户的主组:sudo usermod -g groupname username
这不是我们在这里想要的,尽管:dave 用户应该继续在同名的 dave 组中;我们只是想要 dave 也成为 tutorialinux 组的成员。要将用户添加到组中,而不使其成为该用户的主要组,请使用 -aG 选项(“添加到附加组”):
sudo usermod –aG tutorialinux dave
如果您再次检查 /etc/group,您可以看到 dave 用户现在是三个组的成员:dave、sudoers 和 tutorialinux:
grep dave /etc/groupsudoers:x:27:davedave:x:1000:tutorialinux:x:1001:dave
现在,您可以使用上一章中学到的命令来修改文件所有权和权限,从而控制 tutorialinux 组的所有成员对某些文件和目录的访问。
当特定用户完成 tutorialinux 项目的工作时,您可以在不必修改各个文件和目录权限的情况下进行清理并撤销他们的访问权限。
从组中移除用户 要从组中移除用户,我们可以使用 gpasswd 命令如下:
gpasswd –delete username groupname
移除 Linux 用户 要完全移除 Linux 用户,使用 userdel 命令:
userdel -r account_name
如果您想保留该用户的主目录,请省略(-r / --remove)标志。
移除 Linux 组 对于不再需要的组,还有一个 groupdel 命令:
groupdel groupname
高级:用户到底是什么? 用户和组是 Unix 和 Linux 的一个地方,在这里可以清楚地看到 Unix 和 Linux 的一些非常美妙的特点:这里几乎没有什么魔法。
Linux 用户实际上只是一个用户 ID(UID),这是用户(一个无符号 32 位整数)的简单数字表示。root 用户的 UID 是 0。所有其他用户的 UID 都大于 0。组也是如此。
这些信息不是存储在某个秘密位置、某种二进制格式或只有操作系统才能使用专有数据结构中:用户和组在纯文本文件中定义,通常使用我们在这里涵盖的几个简单命令进行修改。
这种简单性和缺乏魔法意味着普通人(比如一个只有这一章模糊记忆的惊慌失措的开发者)可以快速了解运行系统中用户和组的状态,解决可能来自错误准备的主机环境(缺少必要的应用程序用户)的应用程序错误。它在开发人员面试的“系统工程”部分也派上用场。
因此,为了巩固您对这些工作原理的直觉,这里有一些关于我们在创建和管理用户和组时幕后发生的更多有用事实。
用户元数据/属性 仅由数字定义的用户并不特别有用——没有一些额外的元数据来增色。例如,我在日常的 Linux 或 macOS 机器上使用的帐户,恰好有 UID 502,也可能有:
一个友好的登录名(dave) 它自己的组(dave 组) 各种组成员身份(staff、developer 和 wheel) 登录 shell(bash、zsh 等) 主目录(在 macOS 上为 /Users/dave/,在 Linux 上为 /home/dave/)
如果您好奇,您可以通过运行 id 命令来获取有关当前用户的信息:
# iduid=0(root) gid=0(root) groups=0(root)
默认情况下,有几个文件定义并包含所有这些额外的用户信息:
/etc/passwd 包含用户名、UID、GID、主目录和登录 shell,每个用户占一行,由冒号分隔:root@localhost:~# cat /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync/etc/shadow 包含用户的哈希、加盐密码;它只能由 root 用户读取:root@localhost:~# cat /etc/shadow root:$6$SPevRPxD94AYwtmF$IOp9k15dnaN8FW8RUpDDQlifLPp9pJ3btgJcMfIQEs1kT.ZNjDfX66XBOcPOBZzkRcGOb3Rwq6qTsDQ0jiZNh/:19251:0:99999:7::: daemon::19251:0:99999:7::: bin::19251:0:99999:7::: sys::19251:0:99999:7::: sync::19251:0:99999:7:::/etc/group – 与 /etc/passwd 等效,但是用于组而不是用户。您在本章早些时候看到(并使用)了这个文件。可选地,像 /home/dave 这样的主目录:
# /etc/passwd username:password:UID:GID:comment:home:shell
警告:虽然了解这些文件包含的内容是有意义的,但您应该永远不要手动编辑这些文件。使用我们在前几节中使用的工具来创建、删除或修改系统用户和组。
希望这个关于组成用户和组的动态部分(或更准确地说,静态纯文本文件)的快速理论概述是有启发性的。我们不仅希望确保您对这种工作方式有直觉,而且我们希望本节强调这在底层实际上是多么简单。这里没有魔法!
下次您在排除应用程序无法启动的原因,或者为什么用户没有权限查看具有特定组所有权的某个文件时,您可以确信自己没有错过什么。
关于可脚本化的注释 早些时候,我们提到更喜欢像 useradd 这样的可自动化工具,而不是像 adduser 这样的交互式向导工具——即使这些可自动化工具有点更复杂或难以学习。或许您会问:“为什么不直接使用图形工具,而不是这些难以记住的 CLI 命令呢?”
我们在本书中要教给您的一件事是通常更喜欢非交互式命令。
因为这些命令在运行时不依赖实时用户输入,所以它们是可脚本化的:创建一百个用户几乎和创建一个一样容易。当您处理现实生活中的问题时,这真的很有用,比如构建 Docker 镜像、重复准备生产环境或为您的云实例编写 cloud-init 设置脚本。
作为一名开发者,这应该是有道理的:自动化使事情更可重复、安全和快速。通过学习非交互式命令,您可以保留将该命令作为更大自动化部分的力量,而不是拥有需要容易出错、耗时和风险的手动干预的步骤。
结论 您刚刚学习了 Linux 如何使用用户和组的抽象来管理和控制系统上的进程、文件和其他资源的基础知识。同样重要的是,您学习了在真实系统上创建和管理用户和组所需的基本命令。您了解了 root 用户和系统上所有其他普通用户之间的重要区别。
然后,我们通过一个实际练习,创建了一个用户,向系统添加了一个组,修改了该用户,然后清理了您创建的所有资源。
最后,我们超越了日常命令,向您展示了这里幕后没有魔法:这一切都只是定义 Unix 系统上用户和组的纯文本文件。这是一件好事;无论您是:
创建一个 Docker 镜像来以特定的非 root 用户身份运行您的应用程序。 为您的数据科学团队设置一个带有登录和共享组的长期运行的云实例。 尝试最小化您自己本地测试环境中错误的影响。 排除应用程序上的用户和组错误,例如,需要 root 用户权限才能打开一个秘密文件或在系统上执行特权操作的 Web 应用程序。
在下一章中,我们将利用所有这些知识深入探讨 Unix 安全模型的工作原理,通过查看所有权和权限。