---
title: 第 14 章 用户和基本的帐户管理
part: 部分 III. 系统管理
prev: books/handbook/boot
next: books/handbook/security
showBookMenu: true
weight: 18
params:
  path: "/books/handbook/users/"
---

[[users]]
= 用户和基本的帐户管理
:doctype: book
:toc: macro
:toclevels: 1
:icons: font
:sectnums:
:sectnumlevels: 6
:sectnumoffset: 14
:partnums:
:source-highlighter: rouge
:experimental:
:images-path: books/handbook/users/

ifdef::env-beastie[]
ifdef::backend-html5[]
:imagesdir: ../../../../images/{images-path}
endif::[]
ifndef::book[]
include::shared/authors.adoc[]
include::shared/mirrors.adoc[]
include::shared/releases.adoc[]
include::shared/attributes/attributes-{{% lang %}}.adoc[]
include::shared/{{% lang %}}/teams.adoc[]
include::shared/{{% lang %}}/mailing-lists.adoc[]
include::shared/{{% lang %}}/urls.adoc[]
toc::[]
endif::[]
ifdef::backend-pdf,backend-epub3[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]
endif::[]

ifndef::env-beastie[]
toc::[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]

[[users-synopsis]]
== 概述

FreeBSD允许多个用户同时使用计算机. 当然,这些用户中不是很多人同时坐在同一台计算机前. ,而是其他用户可以通过网络来使用同一台计算机以完成他们的工作.要使用系统,每个人都应该有一个帐户.

读完这章，您将了解到:

* 在一个FreeBSD系统上不同用户帐户之间的区别.
* 如何添加用户帐户.
* 如何删除用户帐户.
* 如何改变帐户细节，如用户的全名，或首选的shell.
* 如何在每个帐户基础上设置限制，来控制像内存，CPU时钟这样的资源.
* 如何使用组来使帐户管理更容易.

在阅读这章之前，您应当了解:

* 了解UNIX(R)和FreeBSD的基础知识 (crossref:basics[basics,UNIX 基础]).

[[users-introduction]]
== 介绍

所有访问系统的用户都是通过帐户完成的，所以用户和帐户管理是FreeBSD系统不可或缺的重要部分.

每个FreeBSD系统的帐户都有一些和它相对应的信息去验证它.

用户名::
用户名在``login:`` 提示符的后面键入。 用户名对于一台计算机来讲是唯一的； 您不可以使用两个相同的用户名来登录。 有很多用来创建正确用户名的规则， 具体请参考 man:passwd[5]； 您使用的用户名通常需要8个或更少的小写字母。

口令::
每个帐户都有一个口令与它对应。 口令可以是空的， 这样不需要口令就可以访问系统。 这通常不是一个好主意； 每个帐户都应该有口令。

用户 ID (UID)::
UID是系统用来识别用户的数字，传统上它的范围是0到65536之间，用以唯一地标识用户。 FreeBSD在内部使用UID来识别用户 - 在工作以前。 任何允许您指定一个用户名的 FreeBSD 命令都会把它转换成UID。 这意味着您可以用不同的用户名使用多个帐户， 但它们的UID是一样的。 FreeBSD 会把这些帐户认定是同一个用户。

组ID (GID)::
GID是用来识别用户所在的组的， 传统上范围在0到65536之间的数字。 组是一种基于用户GID而不是它们的UID的用来控制用户访问资源的机制。 这可以减少一些配置文件的大小。 一个用户也可以属于多个组。

登录类::
登录类是对组机制的扩展,当把系统分配给不同用户时,它提供了额外的灵活性.

口令的定期更改::
默认情况下， FreeBSD 并不强制用户去改变他们的口令。 您可以以用户为单位强制要求一些或所有的用户定期改变他们的口令。

帐户的到期时间::
默认情况下 FreeBSD 不会自动完成帐户过期操作。 如果您正在创建帐户， 您应该知道一个帐户的有效使用期限。 例如， 在学校里您会为每个学生建立一个帐户， 您可以指定它们何时过期。 帐户过期后， 虽然帐户的目录和文件仍然存在， 但帐户已经不能继续使用了。

用户的全名::
用户名可以唯一地识别FreeBSD的帐户， 但它不会反映用户的全名。 这些信息可能与帐户是相关的。

主目录::
主目录是用户用来启动的目录的完全路径。 一个通常的规则是把所有用户的主目录都放在 [.filename]#/home/username# 下，或者 [.filename]#/usr/home/username# 下。 用户将把他们的个人文件放在自己的主目录下， 他们可以在那里创建任何目录.

用户 shell::
Shell提供了用户用来操作系统的默认环境。 有很多不同的shell， 有经验的用户会根据他们的经验来选择自己喜好的shell。

有三种类型的帐户: <<users-superuser,超级用户>>， <<users-system,系统用户>>， 以及 <<users-user,普通用户>>。 超级用户帐户通常叫做 `root`， 可以没有限制地管理系统。 系统用户运行服务。 最后， 普通用户给那些登录系统以及阅读邮件的人使用。

[[users-superuser]]
== 超级用户帐户

超级用户帐户， 通常叫做 `root`， 可以重新配置和管理系统， 在收发邮件， 系统检查或编程这样的日常工作中， 尽量不要使用root权限。

这是因为不象普通用户帐户， 超级用户能够无限制地操作系统， 超级用户帐户的滥用可能会引起无法想象的灾难。 普通的用户帐户不会由于出错而破坏系统， 所以要尽可能的使用普通帐户， 除非您需要额外的特权。

在使用超级用户命令时要再三检查， 因为一个额外的空格或缺少某个字符的命令都可能会引起数据丢失。

所以， 在阅读完这章后您第一件要做的事就是， 在平时使用的时候， 创建一个没有特权的用户帐户。 无论您使用的是单用户还是多用户系统这样的申请都是相同的。 在这章的后面， 我们将讨论如何创建一个额外的帐户和如何在普通用户和超级用户之间进行切换。

[[users-system]]
== 系统帐户

系统用户是那些要使用诸如DNS、 邮件， web等服务的用户。 使用帐户的原因就是安全； 如果所有的用户都由超级用户来运行， 那它们就可以不受约束地做任何事情。

典型的系统帐户包括 `daemon`、 `operator`、 `bind` (供 域名服务 使用)、 `news`， 以及 `www`。

`nobody` 是普通的没有特权的系统用户。 然而， 大多数与用户联系很密切的服务是使用 ``nobody``的， 记的这点非常重要， 这样可能使用户变的非常有特权。

[[users-user]]
== 用户帐户

用户帐户是让真实的用户访问系统的主要方式， 这些帐户把用户和环境隔离， 能阻止用户损坏系统和其他用户， 在不影响其他用户的情况之下定制自己的环境。

任何人访问您的系统必须要有他们自己唯一的帐户。 这可以让您找到谁做了什么事， 并且阻止人们破坏其他用户的设置和阅读其他人的邮件等等。

每个用户能够设置他们自己的环境， 以利于他们通过改变shell， 编辑器， 键盘绑定和语言等适应并且更好的使用这个系统。

[[users-modifying]]
== 修改帐户

在UNIX(R) 的处理用户帐户的环境中有很多不同的命令可用. 最普通的命令如下， 接下来是详细使用它们的例子。

[.informaltable]
[cols="1,1", frame="none", options="header"]
|===
| 命令
| 摘要

|man:adduser[8]
|在命令行添加新用户.

|man:rmuser[8]
|在命令行删除用户.

|man:chpass[1]
|一个灵活的用于修改用户数据库信息的工具.

|man:passwd[1]
|一个用于修改用户口令的简单的命令行工具.

|man:pw[8]
|一个强大灵活修改用户帐户的工具.
|===

[[users-adduser]]
=== `添加用户`

man:adduser[8] 是一个简单的添加新用户的命令. 它为用户创建 [.filename]#passwd# 和 [.filename]#group# 文件。 它也为新用户创建一个主目录， 之后， 它会复制一组默认的配置文件 ("dotfiles") 从 [.filename]#/usr/shared/skel# 这个目录， 然后给新用户发送一封带欢迎信息的邮件。

.在 FreeBSD 中添加一个新用户
[example]
====

[source,shell]
....
# adduser
Username: jru
Full name: J. Random User Uid (Leave empty for default):
Login group [jru]:
Login group is jru. Invite jru into other groups? []: wheel
Login class [default]:
Shell (sh csh tcsh zsh nologin) [sh]: zsh
Home directory [/home/jru]:
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]:
Use a random password? (yes/no) [no]:
Enter password:
Enter password again:
Lock out the account after creation? [no]:
Username   : jru
Password   : ****
Full Name  : J. Random User
Uid        : 1001
Class      :
Groups     : jru wheel
Home       : /home/jru
Shell      : /usr/local/bin/zsh
Locked     : no
OK? (yes/no): yes
adduser: INFO: Successfully added (jru) to the user database.
Add another user? (yes/no): no Goodbye!
#
....

====

[NOTE]
====
您输入的口令并不会回显到屏幕上， 此外系统也不会显示星号。 请务必确保没有输错口令。 
====

[[users-rmuser]]
=== `删除用户`

您可以使用man:rmuser[8] 从系统中完全删除一个用户. man:rmuser[8] 执行如下步骤:

[.procedure]
====
. 删除用户的 man:crontab[1] 记录 (如果有的话).
. 删除属于用户的man:at[1] 工作.
. 杀掉属于用户的所有进程.
. 删除本地口令文件中的用户.
. 删除用户的主目录 (如果他有自己的主目录).
. 删除来自 [.filename]##/var/mail##属于用户的邮件.
. 删除所有诸如 [.filename]##/tmp##的临时文件存储区中的文件.
. 最后, 删除 [.filename]##/etc/group##中所有属于组的该用户名.
+
[NOTE]
======
如果一个组变成空，而组名和用户名一样,组将被删除. man:adduser[8]命令建立每个用户唯一的组.
======
====

man:rmuser[8] 不能用来删除超级用户的帐户, 因为那样做是对系统极大的破坏.

默认情况下, 使用交互模式, 这样能够让您清楚的知道您在做什么.

.`删除用户` 交互模式下的帐户删除
[example]
====

[source,shell]
....
# rmuser jru Matching password entry:
jru:*:1001:1001::0:0:J. Random User:/home/jru:/usr/local/bin/zsh Is this the entry you wish to remove? y Remove user's home directory (/home/jru)? y Updating password file, updating databases, done.
Updating group file: trusted (removing group jru -- personal group is empty) done.
Removing user's incoming mail file /var/mail/jru: done.
Removing files belonging to jru from /tmp: done.
Removing files belonging to jru from /var/tmp: done.
Removing files belonging to jru from /var/tmp/vi.recover: done.
#
....

====

[[users-chpass]]
=== `chpass`

man:chpass[1] 可以改变用户的口令, shells, 和包括个人信息在内的数据库信息.

只有系统管理员， 即超级用户， 才可以用 man:chpass[1] 改变其他用户口令和信息。

除了可选择的用户名， 不需要任何选项， man:chpass[1] 将显示一个包含用户信息的编辑器. 可以试图改变用户在数据库中的信息.

[NOTE]
====
如果您不是超级用户的话， 在退出编辑状态之后， 系统会询问您口令。
====

.以超级用户交互执行 `chpass` 命令
[example]
====

[source,shell]
....
#Changing user database information for jru.
Login: jru
Password: *
Uid [#]: 1001
Gid [# or name]: 1001
Change [month day year]:
Expire [month day year]:
Class:
Home directory: /home/jru
Shell: /usr/local/bin/zsh
Full Name: J. Random User
Office Location:
Office Phone:
Home Phone:
Other information:
....

====

普通用户只能改变他们自己很少的一部分信息.

.以普通用户交互执行 `chpass` 命令
[example]
====

[source,shell]
....
#Changing user database information for jru.
Shell: /usr/local/bin/zsh
Full Name: J. Random User
Office Location:
Office Phone:
Home Phone:
Other information:
....

====

[NOTE]
====
man:chfn[1] 和 man:chsh[1] 只是到 man:chpass[1] 的符号连接， 类似地， man:ypchpass[1], man:ypchfn[1] 以及 man:ypchsh[1] 也是这样。 NIS 是自动支持的， 不一定要在命令前指定 `yp`。 如果这让您有点不太明白， 不必担心， NIS 将在 crossref:network-servers[network-servers,"?"] 介绍。
====

[[users-passwd]]
=== `passwd命令`

man:passwd[1] 是改变您自己作为一个普通用户口令或者作为超级用户口令常用的方法.

[NOTE]
====
用户改变口令前必须键入原来的口令, 防止用户离开终端时非授权的用户进入改变合法用户的口令。
====

.改变您的口令
[example]
====

[source,shell]
....
% passwd Changing local password for jru.
Old password:
New password:
Retype new password:
passwd: updating the database...
passwd: done
....

====

.改变其他用户的口令同超级用户的一样
[example]
====

[source,shell]
....
# passwd jru Changing local password for jru.
New password:
Retype new password:
passwd: updating the database...
passwd: done
....

====

[NOTE]
====
就象 man:chpass[1]一样, man:yppasswd[1] 只是一个到 man:passwd[1]的连接, 所以NIS用任何一个命令都可以正常工作.
====

[[users-pw]]
=== `pw命令`

man:pw[8] 是一个用来创建、删除、修改、显示用户和组的命令行工具。 它还有系统用户和组文件编辑器的功能。 man:pw[8] 有一个非常强大的命令行选项设置， 但新用户可能会觉得它比这里讲的其它命令要复杂很多。

[[users-limiting]]
== 限制用户使用系统资源

如果您有一些用户， 并想要对他们所使用的系统资源加以限制， FreeBSD 提供了一些系统管理员限制用户访问系统资源的方法。 这些限制通常被分为两种: 磁盘配额， 以及其它资源限制。

磁盘配额限制用户对磁盘的使用， 而且它还提供一种快速检查用户使用磁盘数量而不需要时刻计算的方法。 配额将在 crossref:disks[quotas,文件系统配额]讨论.

其它资源限制包括CPU、 内存以及用户可能会使用的其它资源。 这些是通过对登录进行分类完成的， 下面将做讨论。

登录的类由 [.filename]#/etc/login.conf# 文件定义。 比较精确的描述超出了本章的范围， 但 man:login.conf[5] 联机手册会有比较详细的描述。 可以说每个用户都分配到一个登录类 (默认是 `defalut`)， 每个登录类都有一套和它相对应的功能。 登录功能是 `名字=值` 这样的一对值， 其中__名字__ 是一个众所周知的标识符， _值_ 是一个根据名字经过处理得到的任意字符串。 设置登录类和功能相当简单， 在 man:login.conf[5] 联机手册会有比较详细的描述。

[NOTE]
====
系统并不直接读取 [.filename]#/etc/login.conf# 中的配置， 而是采用数据库文件 [.filename]#/etc/login.conf.db# 以提供更快的查找能力。 要从 [.filename]#/etc/login.conf# 文件生成 [.filename]#/etc/login.conf.db#， 应使用下面的命令：

[source,shell]
....
# cap_mkdb /etc/login.conf
....

====

资源限制与普通登录限制是有区别的。 首先， 对于每种限制， 有软限制 (比较常见) 和硬限制之分。 一个软限制可能被用户调整过， 但不会超过硬限制。 越往后可能越低， 但不会升高。 其次， 绝大多数资源限制会分配特定用户的每个进程， 而不是该用户的全部进程。 注意， 这些区别是资源限制的特殊操作所规定的， 不是登录功能框架的完成 (也就是说, 他们__实际上__ 不是一个登录功能的特例)。

不再罗嗦了， 下面是绝大多数资源限制的例子 (您可以在 man:login.conf[5] 找到其它与登录功能相关的内容)。

`coredumpsize`::
很明显， 由程序产生的核心文件大小的限制在磁盘使用上是属于其它限制的 (例如， `文件大小`， 磁盘配额)。 不过， 由于用户自己无法产生核心文件， 而且通常并不删除它们， 设置这个可以尽量避免由于一个大型应用程序的崩溃所造成的大量磁盘空间的浪费。 (例如, emacs) 崩溃。

`cputime`::
这是一个用户进程所能消耗的最长 CPU 时间。 违反限制的进程， 将被内核杀掉。
+
[NOTE]
====
这是一个有关CPU消耗的__时钟__ 限制, 不是man:top[1] 和 man:ps[1] 命令时屏幕上显示的CPU消耗的百分比。 在写此说明时， 后者的限制是不太可能和没有价值的： 编译器 - 编译一个可能是合法的工作 - 可以在某一时刻轻易的用掉 100% 的 CPU。
====

`filesize`::
这是用户可以处理一个文件的最大值。 不象 crossref:disks[quotas,磁盘配额]， 这个限制是对单个文件强制执行的， 不是用户自己的所有文件。

`maxproc`::
这是一个用户可以运行的最大进程数。 这包括前台和后台进程。 很明显， 这不可能比系统指定 `kern.maxproc` man:sysctl[8] 的限制要大。 同时也要注意， 设置的过小会妨碍用户的处理能力： 可能需要多次登录或执行多个管道。 一些任务， 例如编译一些大的程序， 也可能会产生很多进程 (例如， man:make[1]， man:cc[1] 以及其它一些预处理程序)。

`memorylocked`::
这是一个进程允许锁到主存中的最大内存容量 (参见 man:mlock[2])。 大型程序， 例如像 man:amd[8] 在遇到问题时， 它们得到的巨大交换量无法传递给系统进行处理。

`memoryuse`::
这是在给定时间内一个进程可能消耗的最大内存数量。 它包括核心内存和交换内存。 在限制内存消耗方面， 这不是一个完全的限制，但它是一个好的开始。

`openfiles`::
这是一个进程可以打开的最大文件数。 在FreeBSD中， 文件可以被表现为套接字和IPC通道； 注意不要把这个数设置的太小。 系统级的限制是由 `kern.maxfiles` 定义的， 详情参见 man:sysctl[8]。

`sbsize`::
这是网络内存数量的限制， 这主要是针对通过创建许多套接字的老式 DoS 攻击的， 但也可以用来限制网络通信。

`stacksize`::
这是一个进程堆栈可能达到的最大值。 它不能单独的限制一个程序可能使用的内存数量； 所以， 需要与其它的限制手段配合使用。

在设置资源限制时， 有一些其他的事需要注意。 下面是一些通常的技巧、 建议和注意事项。

* 系统启动的进程[.filename]##/etc/rc##会被指派给 `守护程序` 的登录类.
* 虽然 [.filename]#/etc/login.conf# 文件是一个对绝大多数限制做合理配置的资源文件， 但只有您也就是系统管理员，才知道什么最适合您的系统。 设置的太高可能会因为过于开放而导致系统被滥用， 而设置过低， 则可能降低效率。
* 使用 X Window 的用户可能要比其他用户使用更多的资源。 因为X11本身就使用很多资源， 而且它鼓励用户同时运行更多的程序。
* 务必注意， 许多限制措施是针对单个进程来实施的， 它们并不限制某一用户所能用到的总量。 例如， 将 `openfiles` 设置为 50 表示以该用户身份运行的进程最多只能打开 50 个文件。 因而， 用户实际可以打开的文件总数就应该是 `maxproc` 和 `openfiles` 值的乘积。 对内存用量的限额与此类似。

有关资源限制,登录类的更深入信息可以查看相关联机手册: man:cap.mkdb[1], man:getrlimit[2], man:login.conf[5].

[[users-groups]]
== 组

组简单的讲就是一个用户列表. 组通过组名和GID (组 ID) 来识别。 在 FreeBSD (以及绝大多数其他 UNIX(R) 系统) 中， 内核用以决定一个进程是能够完成一项动作的两个因素是它所属的用户 ID 和组 ID。 与用户 ID 不同， 每个进程都有一个和它相关联的组的列表。 您可能听说过用户或进程的 "组 ID"； 大多数情况下， 这表示列表中的第一个组。

与组ID对应的组名在[.filename]##/etc/group##中。 这是一个由冒号来界定的文本文件。 第一部分是组名， 第二部分是加密后的口令， 第三部分是组ID， 第四部分是以逗号相隔的成员列表。 它可以用手工方式进行编辑 (当然， 如果您能保证不出语法错误的话！)。 对于更完整的语法描述， 参见 man:group[5] 联机手册.

如果不想手工编辑 [.filename]#/etc/group#， 也可以使用 man:pw[8] 添加和编辑组。 例如， 要添加一个叫 `teamtwo` 的组， 确定它存在：

.使用man:pw[8]添加一个组
[example]
====

[source,shell]
....
# pw groupadd teamtwo
# pw groupshow teamtwo
teamtwo:*:1100:
....

====

上面的数字 `1100` 是组 `teamtwo` 的组 ID。 目前， `teamtwo` 还没有成员， 因此也就没有多大用处。 接下来， 把 `jru` 加入到 `teamtwo` 组。

.使用 man:pw[8] 设置组的成员列表
[example]
====

[source,shell]
....
# pw groupmod teamtwo -M jru
# pw groupshow teamtwo
teamtwo:*:1100:jru
....

====

`-M` 所需的参数是一个用逗号分隔的组中将要成为成员的用户列表。 前面我们已经知道， 口令文件中， 每个用户已经指定了一个所属组。 之后用户被自动地添加到组列表里； 当我们使用 `groupshow` 命令时 man:pw[8] 用户列表不被显示出来。 但当通过 man:id[1] 或者类似工具查看时， 就会看到用户列表。 换言之， man:pw[8] 命令只能读取 [.filename]#/etc/group# 文件； 它从不尝试从 [.filename]#/etc/passwd# 文件读取更多信息。

.使用 man:pw[8] 为组添加新的成员
[example]
====

[source,shell]
....
# pw groupmod teamtwo -m db
# pw groupshow teamtwo
teamtwo:*:1100:jru,db
....

====

`-m` 选项的参数是一个由逗号分隔的即将被添加进组的用户列表。 与先前那个例子的不同之处在于， 这个列表中的用户将被添加进组而非取代组中的现有用户。

.使用man:id[1]来决定组成员
[example]
====

[source,shell]
....
% id jru
uid=1001(jru) gid=1001(jru) groups=1001(jru), 1100(teamtwo)
....

====

正如您所看到的， `jru` 是组 `jru` 和组 ``teamtwo``的成员.

有关man:pw[8]的更多信息， 请参看其它联机手册。 更多的关于 [.filename]#/etc/group# 文件格式的信息， 请参考 man:group[5] 联机手册。
