4.9 用户和基本账户管理
FreeBSD 系统的所有访问均通过账户实现,所有进程都由用户运行,故用户与账户管理是系统安全的基础。
FreeBSD 提供了多种用户管理工具。adduser 命令以交互方式添加新用户,自动完成创建 passwd 条目、构建新用户主目录、从 /usr/share/skel 复制默认配置文件等操作。
adduser(8) 是一个 Bourne shell 脚本,内部调用 pw(8) 完成实际的用户数据库操作。adduser(8) 是 FreeBSD 特有工具。
pw 命令是更底层的用户和组管理工具,支持非交互式批量操作,可直接修改系统用户数据库文件。
用户账户信息存储在 master.passwd(5) 文件中,该文件包含用户名、加密密码、UID、GID、登录类、密码过期时间、账户过期时间、GECOS 信息、主目录和登录 shell 等字段。
4.9.1 账户类型
登录 FreeBSD 系统需具备有效的用户账户。
以下直接通过密码文件 /etc/master.passwd 观察用户:
root:$6$huh5iMfeueumGM3B$ycd9HsGOzKfFq6hbWMxceNBRCLibbSj5Ofjv/ed6Kq60M2F.syaGaxfdfYMqB79DZzqyhQlIiRZ4.D9ST90Gv/:0:0::0:0:Charlie &:/root:/bin/sh
toor:*:0:0::0:0:Bourne-again Superuser:/root:
daemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin
operator:*:2:5::0:0:System &:/:/usr/sbin/nologin
……省略一部分……
www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin
ntpd:*:123:123::0:0:NTP Daemon:/var/db/ntp:/usr/sbin/nologin
nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin
ykla:$6$SqMJXrv5aC6Wq.by$nmbZs078aHNBVyh9noLFouJsGHyFSvQIzH0W4zpdfXuPtGtt.FHgWfXDHVBa.g9P0eZ32UwfByzRKdVnTaO7W.:1001:1001::0:0:User &:/home/ykla:/bin/sh可以看到系统中存在若干用户账户。
FreeBSD 中主要有三类账户:系统账户、普通用户账户,以及超级用户账户。
4.9.1.1 系统账户
系统账户用于运行 DNS、邮件和 Web 服务器等服务。如果所有服务均以超级用户身份运行,其操作将不受限制,此即使用系统账户的安全性考量。
系统账户由源代码中的 main/etc/master.passwd 文件定义,截至写作时共计 27 个,_dhcp、ntpd 便属于此类系统账户。系统账户是具有受限权限的专用账户,通常用于运行系统服务和守护进程。
nobody 是通用的非特权系统账户,但使用 nobody 的服务越多,该用户关联的文件和进程就越多,该用户特权越大,故而最佳实践是为每个服务分配独立的系统账户,而非共用 nobody。
4.9.1.2 普通用户账户
普通用户账户分配给实际使用者,用于登录和使用系统。为便于管理员追踪用户操作并防止用户互相干扰彼此的设置,每个访问系统的人都应拥有唯一的用户账户。
ykla 是在安装系统时创建的普通用户账户。如果希望通过 su 命令切换为 root 用户,必须将该用户加入 wheel 用户组。此外,部分用户账户是 Port 自动创建的系统用户。
每个用户账户在 FreeBSD 系统上都关联着若干属性信息:
- 用户名:在
login:提示符处输入的名称,每个用户必须拥有唯一的用户名。passwd(5) 中记载了创建有效用户名的规则。建议使用八个或更少的全部小写字符作为用户名,以保持向后兼容性。 - 密码:每个账户都有一个关联的密码。
- 用户 ID(UID):用于在 FreeBSD 系统中唯一标识用户的数字。由于较高的值可能导致某些软件的兼容性问题,建议使用小于 65535 的 UID。
- 组 ID(GID):用于唯一标识用户所属主组的数字。建议使用 65535 或更低的 GID。
- 登录类:组机制的扩展,在为不同用户定制系统时提供额外的灵活性。
- 密码更改时间:在默认情况下密码不会过期,但可以按用户启用密码过期。
- 账户过期时间:在默认情况下 FreeBSD 不会使账户过期。
- 用户全名:用户名唯一标识 FreeBSD 的账户,但不一定反映用户的真实姓名。
- 主目录:用户登录时的起始目录。常见约定是将所有用户主目录放在 /home/username 或 /usr/home/username 下。
- 用户 shell:shell 提供用户与系统交互的默认环境。
需要注意,普通用户权限虽有限,但其运行的软件越多,系统暴露的攻击面也越大——可供攻击者利用的漏洞入口随之增多。攻击者仅在程序存在漏洞或配置不当的情况下,才能利用这些进程实现权限提升。
4.9.1.3 超级用户账户
超级用户账户,通常称为 root,用于无限制地管理系统。超级用户与普通用户账户不同,其操作不受限制,误用可能导致灾难性后果。普通用户账户无法因误操作而破坏操作系统,因此建议以普通用户账户登录,仅在命令需要额外特权时才切换为超级用户。
事实上,内核根据账户的 EUID(有效用户 ID)是否为 0 来判定某账户是否拥有 root 权限。参见:main/sys/kern/kern_priv.c[EB/OL]. [2026-03-26]. https://github.com/freebsd/freebsd-src/blob/main/sys/kern/kern_priv.c 中的 if (suser_enabled(cred)) 代码块部分。
获取超级用户特权有多种方式。虽然可以直接以 root 登录,但不推荐这种做法,建议使用 su(1) 命令切换为超级用户。
4.9.2 账户管理
FreeBSD 提供了多种不同的命令来管理用户账户。
管理用户账户的工具
| 命令 | 概要 |
|---|---|
| adduser(8) | 推荐用于添加新用户的命令行应用程序。 |
| rmuser(8) | 推荐用于删除用户的命令行应用程序。 |
| chpass(1) | 用于更改用户数据库信息的灵活工具。 |
| passwd(1) | 用于更改用户密码的命令行工具。 |
| pw(8) | 可修改用户账户所有方面的强大灵活工具。 |
| bsdconfig(8) | 带有账户管理支持的系统配置工具。 |
4.9.2.1 adduser 创建用户
推荐使用的添加新用户的程序是脚本文件 adduser(8)。添加新用户时,此程序会自动更新 /etc/passwd 和 /etc/group。
adduser 还会为新用户创建主目录,从 /usr/share/skel (源代码路径为 share/skel)复制默认配置文件。adduser 的源代码路径为 usr.sbin/adduser/adduser.sh。
adduser(8) 是交互式的,会逐步引导创建新用户账户。如下所示,输入所需信息或按 回车键 接受方括号中的默认值。
在此示例中,用户受邀加入 wheel 组,使其可以通过 su(1) 成为超级用户。
完成后,该工具会提示是创建另一名用户还是退出。
示例:创建普通用户 ykla,并添加到 video 组:
# adduser -g video -s sh -w yes
# Username: ykla示例:创建用户 test,并添加到 wheel 组,设置其默认 shell 为 sh:
# adduser # 此工具必须由超级用户运行
Username: test # 用户名 ①
Full name: # 全名,可留空
Uid (Leave empty for default): # UID 设置,可留空
Login group [test]: # 登录组
Login group is test. Invite test into other groups? []: wheel # 设置要加入的组,多个用空格隔开,可留空
Login class [default]: # 登录分类,可留空
Shell (sh csh tcsh git-shell bash rbash nologin) [sh]: sh # 除非手动设置默认 Shell,否则 Shell 为 sh
Home directory [/home/test]: # 指定家目录
Home directory permissions (Leave empty for default): # 指定家目录权限
Enable ZFS encryption? (yes/no) [no]: # 是否使用 ZFS 加密
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 : test
Password : *****
Full Name :
Uid : 1002
ZFS dataset : zroot/home/test
Class :
Groups : test wheel
Home : /home/test
Home Mode :
Shell : /bin/sh
Locked : no
OK? (yes/no): yes # 检查是否有错误
adduser: INFO: Successfully created ZFS dataset (zroot/home/test).
adduser: INFO: Successfully added (test) to the user database.
Add another user? (yes/no): no # 还需要创建另一个账户吗?
Goodbye!注意
由于输入密码时不会打印在屏幕上,也不会显示为掩码
*,请谨慎创建用户账户。
- ① 登录名命名有一些限制,参见 passwd(5)[EB/OL]. [2026-03-26]. https://man.freebsd.org/cgi/man.cgi?query=passwd&sektion=5。但请注意,登录名不支持八位编码字符集,例如不支持中文(即仅支持特定 ASCII 字符)。
只有 root 才能使用此命令,否则将提示错误如下:
$ adduser test
adduser: ERROR: you must be the super-user (uid 0) to use this utility.提示只有 UID 0 的用户(通常是 root)才能调用 adduser 命令。
4.9.2.2 rmuser 删除用户
警告
rmuser将永久删除用户账户及其主目录、邮件等所有相关信息,操作不可逆。使用-y参数将跳过确认步骤,请务必确认用户名正确无误。
rmuser 用于删除用户,与 adduser 命令一样,也是交互式的脚本。rmuser 源代码路径是 usr.sbin/adduser/rmuser.sh。
示例:删除用户 test1 test2。
# rmuser -y test1 test2 # 同时删除用户 test1 和 test2
Removing user (test1): mailspool home passwd.
Removing user (test2): home passwd.参数 -y 用于跳过确认步骤。
4.9.2.3 chpass 更改用户信息
所有用户都可以使用 chpass(1) 更改其默认 shell 和账户的个人信息。chpass 源代码位于 usr.bin/chpass。
示例:普通用户使用 nvi 文本编辑器打开当前用户信息并修改。
$ chpass ykla # 修改 ykla 的账户信息数据库
#Changing user information for ykla.
Shell: /bin/sh # 用户 shell
Full Name: User & # 用户全名
Office Location: # 办公地点
Office Phone: # 办公电话
Home Phone: # 家庭电话
Other information: # 其他信息
~
~
~
/etc/pw.ogzb33: unmodified: line 1root 可使用此工具更改任意用户的额外账户信息。
# chpass ykla # 修改 ykla 的账户信息数据库
#Changing user information for ykla.
Login: ykla # 指定 ykla
Password: $6$SqMJXrv5aC6Wq.by$nmbZs078aHNBVyh9noLFouJsGHyFSvQIzH0W4zpdfXuPtGtt.FHgWfXDHVBa
.g9P0eZ32UwfByzRKdVnTaO7W. # 用户密码
Uid [#]: 1001
Gid [# or name]: 1001
Change [month day year]: # 密码更改日期
Expire [month day year]: # 账户过期日期
Class: # 用户分级
Home directory: /home/ykla # 用户家目录
Shell: /bin/sh
Full Name: User &
Office Location:
Office Phone:
Home Phone:
Other information:
~
~
~
/etc/pw.mDp9q3: unmodified: line 1示例:修改用户 test1 的登录环境为 /bin/sh。
# chpass -s sh test1
chpass: user information updated常用参数:-s,用于修改登录 shell。
技巧
chfn(1) 与 chsh(1) 是 chpass(1) 的链接命令,ypchpass(1)、ypchfn(1) 和 ypchsh(1) 也是。由于 NIS 支持是自动的,无需在命令前加
yp。这一点可以从源代码usr.bin/chpass/Makefile进行推断:makefileSYMLINKS= chpass ${BINDIR}/chfn SYMLINKS+= chpass ${BINDIR}/chsh .if ${MK_NIS} != "no" # 如果系统启用了 NIS SYMLINKS+= chpass ${BINDIR}/ypchfn SYMLINKS+= chpass ${BINDIR}/ypchpass SYMLINKS+= chpass ${BINDIR}/ypchsh .endif MLINKS= chpass.1 chfn.1 chpass.1 chsh.1 .if ${MK_NIS} != "no" MLINKS+= chpass.1 ypchpass.1 chpass.1 ypchfn.1 chpass.1 ypchsh.1 .endif
4.9.2.4 passwd 更改用户密码
修改用户密码,如不指定用户则默认为当前用户。普通用户只能修改自己的密码,否则将提示错误如下:
$ passwd test
passwd: permission denied示例:使用 ykla 更改自己的密码。
$ passwd ykla
Changing local password for ykla
Old Password: # 输入旧密码
New Password: # 输入新密码
Retype New Password: # 再次输入新密码root 用户可以修改所有用户的密码,且无需旧密码。
示例:使用 root 更改用户 ykla 的密码。
# passwd ykla
Changing local password for ykla
New Password: # 输入新密码
Retype New Password: # 再次输入新密码技巧
FreeBSD 的
passwd选项与 Linux 不同,锁定/解锁账户请使用pw lock/unlock。
4.9.3 组管理
组是用户的列表。组由其组名和 GID 标识。在 FreeBSD 中,内核使用进程的 UID 和其所属的组列表来确定进程可执行的操作范围。在大多数情况下,用户或进程的 GID 通常指列表中的第一个组。
组名到 GID 的映射列在 /etc/group 中。/etc/group 是纯文本文件,有四个以冒号分隔的字段。
# cat /etc/group
wheel:*:0:root,ykla #
operator:*:5:root
……省略部分输出……
ykla:*:1001:
test:*:1002:可以看到 /etc/group 的格式形如 组名:加密后的密码:GID:成员列表,通过英文冒号分隔。
超级用户可以使用文本编辑器修改 /etc/group,但因编辑错误可能导致严重后果,不建议这样做。建议使用 pw(8) 添加和编辑组。
警告
operator组可能授予意外的类似超级用户的访问权限,包括但不限于关机、重启和访问 /dev 中的所有项目,因此使用该组时请务必小心。
在 FreeBSD 中,可以使用 pw 命令管理用户和组:它是系统用户和组文件的前端。pw(8) 提供了非常强大的命令行选项,适合用于 shell 脚本,但对于新用户来说可能比本节中的其他命令更复杂。
4.9.3.1 添加组
使用 pw(8) 添加组:
# pw groupadd ykla2
# pw groupshow ykla2
ykla2:*:1002:在此示例中,1002 是 ykla2 的 GID。此时,ykla2 没有成员。
4.9.3.2 向组中添加用户
使用 pw(8) 将用户添加到组中。
示例:设置组 test5 的成员为 test1。
# pw groupmod test5 -M test1 # 原有成员会被删除!示例:将用户 ykla 同时添加到 ykla2 和 wheel 组:
# pw usermod ykla -G ykla2,wheel-G 组列表,逗号分隔。
验证如下:
# id ykla
uid=1001(ykla) gid=1001(ykla) groups=1001(ykla),0(wheel),1002(ykla2)示例:将用户 test 添加到 wheel 组(wheel 组为系统默认组,无需创建):
# pw groupmod wheel -m test在此示例中,传递给 -m 的参数是用户列表(逗号分隔),这些用户会追加到组中,并不会替换已有用户。
4.9.3.3 删除组
示例:删除 admin 组:
# pw groupdel admin4.9.3.4 删除组中的用户
示例:从 admin 组里移除用户 ykla:
# pw groupmod admin -d ykla4.9.3.5 添加用户
pw useradd 命令用于新建用户。
示例:创建用户 test1。
# pw useradd test1 # uid 系统默认,test1 组,登录环境 /bin/sh,未创建主目录示例:创建用户 test2。
# pw useradd test2 -u 1200 -m -d /tmp/test -g test2 -G wheel -s sh -c test2 # 创建用户 test2,uid 为 1200,创建主目录,主目录为 /tmp/test,主组为 test2,有 wheel 权限,登录环境 /bin/sh,全名 test24.9.3.6 修改用户信息
pw usermod 命令用于修改用户信息。
示例:
# pw usermod test1 -l test2 # 将用户 test1 重命名为 test2选项 -l 修改用户名。
4.9.3.7 删除用户
pw userdel 命令用于删除用户。
警告
pw userdel -r将永久删除用户及其主目录和所有相关信息,操作不可逆。若主目录为 ZFS 数据集,还会自动销毁该数据集。请确认用户名正确无误。
示例:删除用户 test2 及其主目录。
# pw userdel -r test2常用参数:-r 删除用户,同时删除用户主目录及所有相关信息;如果不使用该参数则信息保留,仅删除用户。若主目录为 ZFS 数据集且已清空,pw(8) 会自动销毁该数据集,但不会处理数据集内的子数据集和快照。
4.9.3.8 显示用户信息
pw usershow 命令用于显示用户信息。
示例:显示用户 test2 的详细信息。
# pw usershow test2
test2:$6$FkxPcs2y.Y8cxyuj$kVDoV1LC.IWKGlSitll3oLArF18aHQYID0JYE.TUuD0YFgba.c7MbGs3xLnmpCZyu1nVKHhNqW2X7a57qN0xg/:1201:1201::0:0:User &:/home/test2:/bin/sh4.9.3.9 修改组信息
pw groupmod 命令用于修改组信息。
示例:修改 test 组的 gid 为 1300。
# pw groupmod test -g 1300示例:将 test 组重命名为 test2。
# pw groupmod test -l test24.9.4 参考文献
- FreeBSD Project. pw(8)[EB/OL]. [2026-03-26]. https://man.freebsd.org/cgi/man.cgi?query=pw&sektion=8. man 页,介绍了用户和组管理命令。
4.9.5 课后习题
- 修改 FreeBSD 源代码,使操作的用户名支持 UTF-8 编码。
- 查看 FreeBSD 中 pw 命令的源代码实现,使其更加现代化。