FreeBSD/amd64 (pc3.example.org) (ttyv0) login:
第 3 章 FreeBSD 基础知识
如果发现翻译错误,请直接 发起PR修改。
目录
3.1. 简介
本章介绍了 FreeBSD 操作系统的基本命令和功能。其中很多内容对于任何类 UNIX 操作系统都是相关的。鼓励新的 FreeBSD 用户仔细阅读本章。
阅读完本章后,您将了解:
-
如何使用和配置虚拟控制台。
-
如何在 FreeBSD 上创建和管理用户和组。
-
UNIX® 文件权限和 FreeBSD 文件标志的工作原理。
-
默认的 FreeBSD 文件系统布局。
-
FreeBSD 磁盘组织。
-
如何挂载和卸载文件系统。
-
进程、守护进程和信号是什么。
-
什么是 shell ,以及如何更改默认的登录环境。
-
如何使用基本文本编辑器。
-
设备和设备节点是什么。
-
如何阅读手册页以获取更多信息。
3.2. 虚拟控制台和终端
除非 FreeBSD 已经配置为在启动时自动启动图形环境,否则系统将启动到一个命令行登录提示符,如下面的示例所示:
第一行包含了关于系统的一些信息。 amd64
表示 FreeBSD 运行在一个 64 位的 x86 系统上。主机名是 pc3.example.org
,而 ttyv0
表示这是“系统控制台”。第二行是登录提示符。
由于 FreeBSD 是一个多用户系统,它需要一种区分不同用户的方式。这通过要求每个用户在访问系统上的程序之前先登录系统来实现。每个用户都有一个唯一的“用户名”和个人的“密码”。
要登录系统控制台,请输入在系统安装过程中配置的用户名,如 Add Users 中所述,并按下 Enter 键。然后输入与用户名关联的密码并按下 Enter 键。出于安全原因,密码不会显示出来。
一旦输入正确的密码,将显示当天的消息( MOTD ),然后显示命令提示符。根据创建用户时选择的 shell 不同,该提示符可能是 #
、 $
或 %
字符。提示符表示用户已成功登录到 FreeBSD 系统控制台,并准备尝试可用的命令。
3.2.1. 虚拟控制台
虽然系统控制台可以用于与系统进行交互,但在 FreeBSD 系统的键盘命令行上工作的用户通常会登录到虚拟控制台。这是因为系统消息默认配置为显示在系统控制台上。这些消息会出现在用户正在操作的命令或文件上,使得集中注意力于手头的工作变得困难。
默认情况下,FreeBSD 配置了多个虚拟控制台用于输入命令。每个虚拟控制台都有自己的登录提示符和 Shell ,并且可以轻松地在虚拟控制台之间切换。这基本上提供了在图形环境中同时打开多个窗口的命令行等效功能。
组合键 Alt+F1 到 Alt+F8 已被 FreeBSD 保留用于在虚拟控制台之间切换。使用 Alt+F1 切换到系统控制台( ttyv0
),使用 Alt+F2 访问第一个虚拟控制台( ttyv1
),使用 Alt+F3 访问第二个虚拟控制台( ttyv2
),依此类推。当使用 Xorg 作为图形控制台时,组合键变为 Ctrl+Alt+F1 以返回到基于文本的虚拟控制台。
当从一个控制台切换到下一个控制台时,FreeBSD 会管理屏幕输出。结果是有多个虚拟屏幕和键盘可以用来键入命令以供 FreeBSD 运行。当用户切换到不同的虚拟控制台时,在一个虚拟控制台中启动的程序不会停止运行
请参考 kbdcontrol(1) 、 vidcontrol(1) 、 atkbd(4) 、 syscons(4) 和 vt(4) ,以获取更详细的 FreeBSD 控制台及其键盘驱动程序的技术描述。
在 FreeBSD 中,可用的虚拟控制台数量是在 /etc/ttys
文件的这个部分进行配置的:
# name getty type status comments # ttyv0 "/usr/libexec/getty Pc" xterm on secure # Virtual terminals ttyv1 "/usr/libexec/getty Pc" xterm on secure ttyv2 "/usr/libexec/getty Pc" xterm on secure ttyv3 "/usr/libexec/getty Pc" xterm on secure ttyv4 "/usr/libexec/getty Pc" xterm on secure ttyv5 "/usr/libexec/getty Pc" xterm on secure ttyv6 "/usr/libexec/getty Pc" xterm on secure ttyv7 "/usr/libexec/getty Pc" xterm on secure ttyv8 "/usr/X11R6/bin/xdm -nodaemon" xterm off secure
要禁用虚拟控制台,请在表示该虚拟控制台的行的开头放置一个注释符号( #
)。例如,要将可用虚拟控制台的数量从八个减少到四个,请在表示虚拟控制台 ttyv5
到 ttyv8
的最后四行前面放置一个 #
。 不要 注释掉系统控制台 ttyv0
的行。请注意,如果已经安装并配置了 Xorg (如 X Window 系统 中所述),则最后一个虚拟控制台( ttyv8
)用于访问图形环境。
有关此文件中每个列的详细描述以及虚拟控制台的可用选项,请参阅 ttys(5) 。
3.2.2. 单用户模式
FreeBSD 引导菜单提供了一个标有“单用户启动”的选项。如果选择了这个选项,系统将启动到一个称为“单用户模式”的特殊模式。通常情况下,这个模式用于修复无法启动的系统或者在不知道 root
密码时重置密码。在单用户模式下,网络和其他虚拟控制台是不可用的。然而,系统完全支持 root
访问,并且默认情况下不需要 root
密码。因此,需要有对键盘的物理访问权限才能进入该模式,确定谁对键盘有物理访问权是保护 FreeBSD 系统安全时需要考虑的问题
控制单用户模式的设置位于 /etc/ttys
文件的这个部分。
# name getty type status comments # # If console is marked "insecure", then init will ask for the root password # when going to single-user mode. console none unknown off secure
默认情况下,状态被设置为 secure
。这意味着对键盘具有物理访问权限的人要么不重要,要么受到物理安全策略的控制。如果将此设置更改为 insecure
,则假设环境本身是不安全的,因为任何人都可以访问键盘。当将此行更改为 insecure
时, FreeBSD 将在用户选择进入单用户模式时提示输入 root
密码。
在更改此设置为 |
3.2.3. 更改控制台视频模式
FreeBSD 控制台的默认视频模式可以调整为 1024x768 、 1280x1024 或其他由图形芯片和显示器支持的尺寸。要使用不同的视频模式,请加载 VESA
模块:
# kldload vesa
要确定硬件支持哪些视频模式,请使用 vidcontrol(1) 。要获取支持的视频模式列表,请执行以下操作:
# vidcontrol -i mode
该命令的输出列出了硬件支持的视频模式。要选择一个新的视频模式,请使用 vidcontrol(1) 作为 root
用户指定该模式:
# vidcontrol MODE_279
如果新的视频模式可接受,可以通过将其添加到 /etc/rc.conf
来在启动时永久设置。
allscreens_flags="MODE_279"
3.3. 用户和基本账户管理
FreeBSD 允许多个用户同时使用计算机。虽然一次只能有一个用户坐在屏幕前使用键盘,但任意数量的用户可以通过网络登录系统。为了使用系统,每个用户都应该有自己的用户账户。
本章描述了:
-
FreeBSD 系统上的不同类型的用户账户。
-
如何添加、删除和修改用户账户。
-
如何设置限制以控制用户和组可以访问的资源。
-
如何创建组并将用户添加为组的成员。
3.3.1. 账户类型
由于所有对 FreeBSD 系统的访问都是通过账户实现的,并且所有进程都是由用户运行的,因此用户和账户管理非常重要。
有三种主要类型的账户:系统账户、用户账户和超级用户账户。
3.3.1.1. 系统账户
系统账户用于运行诸如 DNS、邮件和 Web 服务器等服务。这样做的原因是出于安全考虑;如果所有服务都以超级用户身份运行,它们就可以无限制地执行操作。
系统账户的例子包括 daemon
、operator
、bind
、news
和 www
。
nobody
是一个通用的非特权系统账户。然而,使用 nobody
的服务越多,与该用户相关联的文件和进程也就越多,因此该用户的特权也就越高。
3.3.1.2. 用户账户
用户账户分配给真实的人,并用于登录和使用系统。每个访问系统的人都应该拥有一个唯一的用户账户。这使管理员能够查明谁在做什么,并防止用户破坏其他用户的设置。
每个用户都可以设置自己的环境以适应他们对系统的使用,通过配置他们的默认 shell 、编辑器、键绑定和语言设置。
在 FreeBSD 系统上,每个用户账户都有与之关联的特定信息:
- User name
-
用户名称是在
login:
提示处输入的。每个用户必须有一个唯一的用户名。有一些创建有效用户名的规则,这些规则在 passwd(5) 中有详细说明。建议使用由八个或更少个小写字符组成的用户名,以保持与应用程序的向后兼容性。 - Password
-
每个账户都有一个关联的密码。
- User ID (UID)
-
用户 ID (UID) 是一个用于在 FreeBSD 系统中唯一标识用户的数字。允许指定用户名的命令将首先将其转换为 UID 。建议使用小于 65535 的 UID ,因为较高的值可能会导致某些软件的兼容性问题。
- Group ID (GID)
-
组 ID (GID) 是一个用于唯一标识用户所属的主要组的数字。组是一种基于用户的 GID 而不是 UID 来控制对资源访问的机制。这可以显著减小某些配置文件的大小,并允许用户成为多个组的成员。建议使用 65535 或更低的 GID ,因为较高的 GID 可能会破坏某些软件。
- Login class
-
登录分级是组机制的扩展,为定制系统以适应不同用户提供了额外的灵活性。有关登录类的详细讨论,请参阅 配置登录分级 。
- Password change time
-
默认情况下,密码不会过期。然而,可以根据每个用户的情况启用密码过期功能,强制一些或所有用户在一定时间后更改他们的密码。
- Account expiration time
-
默认情况下, FreeBSD 不会使账户过期。当创建需要有限生命周期的账户时,比如学校的学生账户,可以使用 pw(8) 命令指定账户的过期日期。在过期时间到达后,该账户将无法用于登录系统,但账户的目录和文件将保留。
- User’s full name
-
用户名在 FreeBSD 中唯一标识账户,但不一定反映用户的真实姓名。与注释类似,此信息可以包含空格、大写字符,并且可以超过 8 个字符的长度。
- Home directory
-
主目录是系统上一个目录的完整路径。这是用户登录时的起始目录。一个常见的约定是将所有用户的主目录放在
/home/username
或/usr/home/username
下。每个用户在自己的主目录中存储个人文件和子目录。 - User shell
-
Shell 提供了用户与系统进行交互的默认环境。有许多不同类型的 shell ,有经验的用户会根据自己的偏好进行设置,这些设置可以反映在他们的账户设置中。
3.3.1.3. 超级用户账户
超级用户账户通常被称为 root
,用于无限制地管理系统。因此,不应将其用于日常任务,如发送和接收邮件、系统的一般探索或编程。
与其他用户账户不同,超级用户可以无限制地操作,滥用超级用户账户可能导致灾难性后果。用户账户无法通过错误操作销毁操作系统,因此建议以用户账户登录,并且只在需要额外权限的命令时切换为超级用户。
作为超级用户,始终要仔细检查任何发出的命令,因为额外的空格或缺失的字符可能导致无法修复的数据丢失。
有几种方法可以获得超级用户权限。虽然可以使用 root
账户登录,但这是极不推荐的。
相反,使用 su(1) 命令成为超级用户。如果在运行此命令时指定了 -
,用户还将继承 root 用户的环境。运行此命令的用户必须属于 wheel
组,否则命令将失败。用户还必须知道 root
用户账户的密码。
在这个例子中,用户只是为了运行 make install
这个步骤需要超级用户权限,才成为超级用户。一旦命令完成,用户输入 exit
来退出超级用户账户,返回到他们的用户账户的权限。
% configure
% make
% su -
Password:
# make install
# exit
%
内置的 su(1) 框架适用于单个系统或只有一个系统管理员的小型网络。另一种选择是安装 security/sudo 软件包或 port。该软件提供活动日志记录,并允许管理员配置哪些用户可以以超级用户身份运行哪些命令。
3.3.2. 管理账户
FreeBSD 提供了多种不同的命令来管理用户账户。最常见的命令在 管理用户账户的实用工具 中进行了总结,并附有一些使用示例。有关每个实用程序的更多详细信息和使用示例,请参阅其手册页面。
命令 |
摘要 |
---|---|
用于添加新用户的推荐命令行应用程序。 |
|
用于删除用户的推荐命令行应用程序。 |
|
用于更改用户数据库信息的灵活工具。 |
|
用于更改用户密码的命令行工具。 |
|
功能强大而灵活的工具,可对用户账户进行全方位修改。 |
|
具有账户管理支持的系统配置工具。 |
3.3.2.1. 添加用户
添加新用户的推荐程序是 adduser(8) 。当添加新用户时,该程序会自动更新 /etc/passwd
和 /etc/group
文件。它还会为新用户创建一个家目录,并从 /usr/share/skel
目录中复制默认配置文件,并可选择向新用户发送欢迎消息。此实用程序必须以超级用户身份运行。
adduser(8) 实用程序是交互式的,并且会引导用户完成创建新用户账户的步骤。如在 在 FreeBSD 上添加用户 中所示,可以输入所需信息,或按 Return 键接受方括号中显示的默认值。在本示例中,用户已被邀请加入 wheel
组,允许他们通过 su(1) 成为超级用户。完成后,实用程序将提示是否创建另一个用户或退出。
# 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!
由于密码在输入时不会显示出来,请在创建用户账户时小心不要输入错误的密码。 |
3.3.2.2. 删除用户
要完全从系统中删除用户,请以超级用户身份运行 rmuser(8) 。该命令执行以下步骤:
-
如果存在用户的 crontab(1) 条目,则删除它。
-
删除用户拥有的所有 at(1) 作业。
-
向用户拥有的所有进程发送 SIGKILL 信号。
-
从系统的本地密码文件中删除用户。
-
删除用户的主目录(如果该目录属于该用户),包括处理路径中符号链接指向实际主目录的情况。
-
从
/var/mail
目录中删除属于用户的传入邮件文件。 -
从
/tmp
、/var/tmp
和/var/tmp/vi.recover
中删除用户所有拥有的文件。 -
将用户名从
/etc/group
中所属的所有组中删除。(如果一个组变为空,并且组名与用户名相同,则删除该组;这与 adduser(8) 的每个用户唯一组相对应。) -
删除用户拥有的所有消息队列、共享内存段和信号量。
rmuser(8) 不能用于删除超级用户账户,因为这几乎总是意味着大规模破坏的迹象。
默认情况下,使用交互模式,如下例所示。
rmuser
交互式账户删除# 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 Removing user (jru): mailspool home passwd.
3.3.2.3. 更改用户信息
任何用户都可以使用 chpass(1) 命令来更改其默认 shell 和与其用户账户关联的个人信息。超级用户可以使用此实用程序来更改任何用户的其他账户信息。
当没有传递任何选项时,除了可选的用户名外, chpass(1) 会显示一个包含用户信息的编辑器。当用户从编辑器退出时,用户数据库将会更新为新的信息。
该实用程序在退出编辑器时会提示用户输入密码,除非以超级用户身份运行该实用程序。 |
在 以超级用户身份使用 chpass
命令 中,超级用户输入了 chpass jru
,现在正在查看可以更改该用户的字段。如果 jru
运行此命令,只有最后六个字段将被显示并可供编辑。这在 以普通用户身份使用 chpass
命令 中显示。
chpass
命令# chpass
输出应该类似于以下内容:
# 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
命令#Changing user database information for jru.
Shell: /usr/local/bin/zsh
Full Name: J. Random User
Office Location:
Office Phone:
Home Phone:
Other information:
3.3.2.4. 更改用户密码
任何用户都可以使用 passwd(1) 轻松更改他们的密码。为了防止意外或未经授权的更改,在设置新密码之前,该命令会提示用户输入原始密码:
% passwd
输出应该类似于以下内容:
Changing local password for jru. Old password: New password: Retype new password: passwd: updating the database... passwd: done
超级用户可以通过在运行 passwd(1) 时指定用户名来更改任何用户的密码。当以超级用户身份运行此实用程序时,它不会提示用户输入当前密码。这允许在用户无法记住原始密码时更改密码。
# passwd jru
输出应该类似于以下内容:
Changing local password for jru. New password: Retype new password: passwd: updating the database... passwd: done
与 chpass(1) 一样, yppasswd(1) 是指向 passwd(1) 的链接,因此 NIS 可以与任一命令一起使用。 |
3.3.3. 管理群组
组是一个用户列表。组由组名称和 GID 标识。在 FreeBSD 中,内核使用进程的 UID 和其所属的组列表来确定该进程被允许做什么。大多数情况下,用户或进程的 GID 通常表示列表中的第一个组。
组名到 GID 的映射在 /etc/group
中列出。这是一个纯文本文件,包含四个由冒号分隔的字段。第一个字段是组名,第二个字段是加密密码,第三个字段是 GID ,第四个字段是逗号分隔的成员列表。有关语法的更完整描述,请参阅 group(5) 。
超级用户可以使用文本编辑器修改 /etc/group
文件,尽管使用 vigr(8) 编辑组文件更为推荐,因为它可以捕捉一些常见的错误。另外,也可以使用 pw(8) 来添加和编辑组。例如,要添加一个名为 teamtwo
的组,并确认它是否存在:
在使用操作员组时必须小心,因为可能会授予意外的类似超级用户的访问权限,包括但不限于关闭、重启以及访问组中 |
# pw groupadd teamtwo
# pw groupshow teamtwo
输出应该类似于以下内容:
teamtwo:*:1100:
在这个例子中,1100
是 teamtwo
的 GID 。目前,teamtwo
没有成员。这个命令将会把 jru
添加为 teamtwo
的成员。
# pw groupmod teamtwo -M jru
# pw groupshow teamtwo
输出应该类似于以下内容:
teamtwo:*:1100:jru
-M
参数后面是一个逗号分隔的用户列表,用于将这些用户添加到一个新的(空的)组中,或者替换现有组的成员。对于用户来说,这个组成员身份与密码文件中列出的用户的主组不同,而且是额外的。这意味着当使用 groupshow
和 pw(8) 一起查看用户时,用户不会显示为组成员,但是当使用 id(1) 或类似的工具查询信息时,用户会显示为组成员。当使用 pw(8) 将用户添加到组时,它只操作 /etc/group
文件,并不尝试从 /etc/passwd
中读取额外的数据。
# pw groupmod teamtwo -m db
# pw groupshow teamtwo
输出应该类似于以下内容:
teamtwo:*:1100:jru,db
在这个例子中, -m
参数后面是一个逗号分隔的用户列表,这些用户将被添加到该组中。与前一个例子不同的是,这些用户会被追加到该组中,而不会替换掉组中已有的用户。
% id jru
输出应该类似于以下内容:
uid=1001(jru) gid=1001(jru) groups=1001(jru), 1100(teamtwo)
在这个例子中,jru
是 jru
和 teamtwo
组的成员。
3.4. 权限
在 FreeBSD 中,每个文件和目录都有一组关联的权限,并且有几个实用程序可用于查看和修改这些权限。要确保用户能够访问所需的文件,并且不能不正当地访问操作系统使用的文件或其他用户拥有的文件,就必须了解权限的工作原理。
本节讨论了在 FreeBSD 中使用的传统 UNIX® 权限。要进行更精细的文件系统访问控制,请参考 访问控制列表 。
在 UNIX® 中,基本权限使用三种类型的访问进行分配:读取、写入和执行。这些访问类型用于确定文件的所有者、组和其他人(其他所有人)对文件的访问。读取、写入和执行权限可以用字母 r
、w
和 x
表示。它们也可以表示为二进制数字,因为每个权限都是打开或关闭的(0
)。当表示为数字时,顺序总是按照 rwx
读取,其中 r
的打开值为 4
, w
的打开值为 2
, x
的打开值为 1
。
表 4.1 总结了可能的数字和字母组合。在阅读“目录列表”列时,使用 -
表示权限关闭。
值 | 权限 | 目录列表 |
---|---|---|
0 |
禁止读取,禁止写入,禁止执行 |
|
1 |
禁止读取,禁止写入,可执行 |
|
2 |
禁止读取,可写入,禁止执行 |
|
3 |
禁止读取,可写入,可执行 |
|
4 |
可读取,禁止写入,禁止执行 |
|
5 |
可读取,禁止写入,可执行 |
|
6 |
可读取、可写入,禁止执行 |
|
7 |
可读取,可写入,可执行 |
|
使用 -l
参数与 ls(1)
一起,可以查看一个包含有关文件所有者、组和其他人权限的列的长目录列表。例如,在任意目录中使用 ls -l
可能会显示:
% ls -l
输出应该类似于以下内容:
total 530 -rw-r--r-- 1 root wheel 512 Sep 5 12:31 myfile -rw-r--r-- 1 root wheel 512 Sep 5 12:31 otherfile -rw-r--r-- 1 root wheel 7680 Sep 5 12:31 email.txt
关注 myfile
这一行,第一个(最左边的)字符表示该文件是普通文件、目录、特殊字符设备、套接字还是其他特殊伪文件设备。在这个例子中, -
表示普通文件。接下来的三个字符 rw-
表示文件所有者的权限。再接下来的三个字符 r--
表示文件所属组的权限。最后三个字符 r--
表示其他用户的权限。破折号表示权限被关闭。在这个例子中,权限被设置为文件所有者可以读写文件,文件所属组可以读取文件,其他用户只能读取文件。根据上面的表格,该文件的权限将是 644
,其中每个数字代表文件权限的三个部分。
系统如何控制设备的权限? FreeBSD 将大多数硬件设备视为程序可以打开、读取和写入数据的文件。这些特殊设备文件存储在 /dev/
目录中。
目录也被视为文件。它们具有读取、写入和执行权限。目录的可执行位与文件的可执行位略有不同。当一个目录被标记为可执行时,意味着可以使用 cd(1) 命令进入该目录。这也意味着可以访问该目录中的文件,但受文件本身权限的限制。
为了执行目录列表,必须在目录上设置读取权限。为了删除一个已知文件名的文件,必须对包含该文件的目录具有写入和执行权限。
还有更多的权限位,但它们主要用于特殊情况,比如 setuid 二进制文件和粘滞目录。有关文件权限及如何设置它们的更多信息,请参考 chmod(1) 。
3.4.1. 符号权限
符号权限使用字符而不是八进制值来为文件或目录分配权限。符号权限使用以下语法: (用户) (动作) (权限) ,可用的值如下:
选项 | 参数 | 意义 |
---|---|---|
(用户) |
u |
用户 |
(用户) |
g |
组所有者 |
(用户) |
o |
其他 |
(用户) |
a |
所有("全部") |
(动作) |
+ |
添加权限 |
(动作) |
- |
移除权限 |
(动作) |
= |
指定权限 |
(权限) |
r |
读 |
(权限) |
w |
写 |
(权限) |
x |
执行 |
(权限) |
t |
粘性位 |
(权限) |
s |
设置用户 ID 或组 ID |
这些值与 chmod(1) 一起使用,但使用字母而不是数字。例如,以下命令将阻止与 FILE 关联的组的所有成员以及所有其他用户访问 FILE。
% chmod go= FILE
当需要对文件进行多组更改时,可以提供逗号分隔的列表。例如,以下命令会移除文件 FILE 的组和 "world" 的写权限,并为所有人添加执行权限:
% chmod go-w,a+x FILE
3.4.2. FreeBSD 文件标志
除了文件权限之外,FreeBSD 还支持使用“文件标志”。这些标志为文件提供了额外的安全性和控制,但不适用于目录。通过文件标志,即使是 root
也可以被阻止删除或更改文件。
使用 chflags(1) 命令可以修改文件标志。例如,要在文件 file1
上启用系统不可删除标志,执行以下命令:
# chflags sunlink file1
要禁用系统不可删除标志,请在 sunlink
前面加上 "no" :
# chflags nosunlink file1
要查看文件的标志,可以使用 -lo
与 ls(1) 一起使用:
# ls -lo file1
-rw-r--r-- 1 trhodes trhodes sunlnk 0 Mar 1 05:54 file1
只有 root
用户才能添加或删除一些文件标志。在其他情况下,文件所有者可以设置其文件标志。有关更多信息,请参阅 chflags(1) 和 chflags(2)。
3.4.3. setuid 、setgid 和 sticky 权限
除了已经讨论过的权限之外,还有三个其他特定的设置,所有管理员都应该了解。它们是 setuid
、setgid
和 sticky
权限。
这些设置对于某些 UNIX® 操作非常重要,因为它们提供了通常不授予普通用户的功能。要理解它们,必须注意实际用户 ID 和有效用户 ID 之间的区别。
真实用户 ID 是拥有或启动进程的 UID 。有效 UID 是进程运行的用户 ID 。例如,当用户更改密码时, passwd(1) 以真实用户 ID 运行。然而,为了更新密码数据库,该命令以 root
用户的有效 ID 运行。这使得用户可以在不看到 权限被拒绝
错误的情况下更改密码。
可以通过为用户添加 s
权限来以符号方式添加 setuid 权限,示例如下:
# chmod u+s suidexample.sh
在下面的示例中,也可以通过在权限集前加上数字四(4)来设置 setuid 权限:
# chmod 4755 suidexample.sh
suidexample.sh
的权限现在如下所示:
-rwsr-xr-x 1 trhodes trhodes 63 Aug 29 06:36 suidexample.sh
请注意,现在文件所有者的权限集中包含了一个 s
,取代了可执行位。这允许使用需要提升权限的实用程序,例如 passwd(1) 。
|
要实时查看此内容,请打开两个终端。在其中一个终端上,以普通用户身份输入 passwd
。在等待新密码时,检查进程表并查看 passwd(1) 的用户信息。
在终端 A 中:
Changing local password for trhodes
Old Password:
在终端 B 中:
# ps aux | grep passwd
trhodes 5232 0.0 0.2 3420 1608 0 R+ 2:10AM 0:00.00 grep passwd
root 5211 0.0 0.2 3620 1724 2 I+ 2:09AM 0:00.01 passwd
尽管 passwd(1) 以普通用户身份运行,但它使用的是 root
的有效 UID 。
setgid
权限与 setuid
权限执行相同的功能,只是它改变的是组的设置。当一个应用程序或实用工具以此设置运行时,它将根据拥有文件的组而不是启动进程的用户被授予权限。
要在文件上以符号方式设置 setgid
权限,请使用 chmod(1) 命令为组添加 s
权限。
# chmod g+s sgidexample.sh
或者,给 chmod(1) 命令提供一个前缀的数字 2 :
# chmod 2755 sgidexample.sh
在下面的清单中,请注意 s
现在位于用于组权限设置的字段中:
-rwxr-sr-x 1 trhodes trhodes 44 Aug 31 01:49 sgidexample.sh
在这些示例中,尽管所讨论的 shell 脚本是一个可执行文件,但它不会以不同的 EUID 或有效用户 ID 运行。这是因为 shell 脚本可能无法访问 setuid(2) 系统调用。 |
setuid
和 setgid
权限位可能会降低系统安全性,因为它们允许提升权限。而第三个特殊权限位,即 sticky bit
,可以增强系统的安全性。
当目录上设置了 粘着位(sticky bit)
时,只允许文件所有者删除文件。这对于防止非文件所有者在公共目录(如 /tmp
)中删除文件非常有用。要使用此权限,请将 t
模式添加到文件中:
# chmod +t /tmp
或者,将权限集以数字 1 作为前缀:
# chmod 1777 /tmp
sticky bit
权限将显示为权限集的最后一个字符 t
。
# ls -al / | grep tmp
drwxrwxrwt 10 root wheel 512 Aug 31 01:49 tmp
3.5. 目录结构
FreeBSD 目录层次结构对于全面了解系统至关重要。最重要的目录是根目录或者“/”。这个目录是在启动时首先挂载的,它包含了准备操作系统进行多用户操作所需的基本系统。根目录还包含其他文件系统的挂载点,在切换到多用户操作时会挂载这些文件系统。
挂载点是一个目录,可以将额外的文件系统嵌入到父文件系统(通常是根文件系统)上。这在 磁盘组织 中有进一步描述。标准的挂载点包括 /usr/
、/var/
、/tmp/
、/mnt/
和 /cdrom/
。这些目录通常在 /etc/fstab
中引用。这个文件是一个包含各种文件系统和挂载点的表格,并由系统读取。除非它们的条目包含 noauto
,否则 /etc/fstab
中的大多数文件系统会在启动时自动从脚本 rc(8) 挂载。详细信息可以在 fstab 文件 中找到。
文件系统层次结构的完整描述可以在 hier(7) 中找到。下表提供了最常见目录的简要概述。
目录 |
描述 |
---|---|
|
文件系统的根目录。 |
|
单用户和多用户环境的基本用户实用程序。 |
|
操作系统引导过程中使用的程序和配置文件。 |
|
默认的启动配置文件。有关详细信息,请参阅 loader.conf(5) 。 |
|
由 devfs(5) 管理的设备特殊文件。 |
|
系统配置文件和脚本。 |
|
默认系统配置文件。有关详细信息,请参阅 rc(8) 。 |
|
通过 cron(8) 每天、每周和每月运行的脚本。有关详细信息,请参阅 periodic(8) 。 |
|
|
|
关键系统文件 |
|
包含用作可移动介质(如 CD、USB 驱动器和软盘)的挂载点的子目录。 |
|
空目录通常被系统管理员用作临时挂载点。 |
|
自动挂载的 NFS 共享;请参阅 auto_master(5) 。 |
|
进程文件系统。有关详细信息,请参阅 procfs(5) 和 mount_procfs(8) 。 |
|
用于紧急恢复的静态链接程序,如 rescue(8) 中所述。 |
|
|
|
单用户和多用户环境的基本系统程序和管理工具。 |
|
通常在系统重新启动后不会保留的临时文件。基于内存的文件系统通常会挂载在 |
|
大多数用户工具和应用程序。 |
|
常用工具、编程工具和应用程序。 |
|
标准的 C 头文件。 |
|
库文件 |
|
杂项实用数据文件。 |
|
系统守护进程和由其他程序执行的系统实用工具。 |
|
本地可执行文件和库。也被用作 FreeBSD ports 框架的默认目的地。在 |
|
FreeBSD Ports 集合(可选)。 |
|
系统守护进程和由用户执行的系统实用程序。 |
|
与体系结构无关的文件。 |
|
BSD 或本地源文件。 |
|
多用途日志、临时、暂存和溢出文件。 |
|
杂项系统日志文件。 |
|
通常在系统重启后保留的临时文件。 |
3.6. 磁盘组织
FreeBSD 使用的最小组织单位是文件名。文件名区分大小写,这意味着 readme.txt
和 README.TXT
是两个不同的文件。 FreeBSD 不使用文件的扩展名来确定文件是程序、文档还是其他形式的数据。
文件存储在目录中。一个目录可以不包含任何文件,也可以包含数百个文件。一个目录还可以包含其他目录,从而允许在彼此之间建立目录层次结构以组织数据。
文件和目录的引用是通过给出文件或目录名称,后跟一个斜杠 /
,再跟上其他必要的目录名称来完成的。例如,如果目录 foo
包含一个目录 bar
,该目录又包含文件 readme.txt
,那么文件的完整名称,或者路径,就是 foo/bar/readme.txt
。请注意,这与 Windows® 不同,Windows 使用反斜杠 \
来分隔文件和目录名称。 FreeBSD 在路径中不使用驱动器号或其他驱动器名称。例如,在 FreeBSD 上,不会输入 c:\foo\bar\readme.txt
。
3.6.1. 文件系统
目录和文件存储在文件系统中。每个文件系统在最顶层都包含一个目录,称为该文件系统的根目录。这个根目录可以包含其他目录。一个文件系统被指定为根文件系统或 /
。其他所有文件系统都被挂载在根文件系统下。无论 FreeBSD 系统上有多少个磁盘,每个目录都看起来是同一个磁盘的一部分。
考虑三个文件系统,分别称为 A
、B
和 C
。每个文件系统都有一个根目录,其中包含两个其他目录,分别称为 A1
、A2
(同样也有 B1
、B2
和 C1
、C2
)。
将 A
称为根文件系统。如果使用 ls(1) 命令查看该目录的内容,将显示两个子目录,A1
和 A2
。目录树如下所示:
一个文件系统必须被挂载到另一个文件系统的目录上。当将文件系统 B
挂载到目录 A1
上时,B
的根目录将替换 A1
,并且 B
中的目录会相应地显示出来:
任何位于 B1
或 B2
目录中的文件可以通过路径 /A1/B1
或 /A1/B2
访问。任何位于 /A1
中的文件都被临时隐藏了。如果从 A
卸载 B
,它们将重新出现。
如果 B
被安装在 A2
上,那么图表将如下所示:
路径分别为 /A2/B1
和 /A2/B2
。
文件系统可以相互叠加挂载。继续上一个例子,C
文件系统可以被挂载在 B
文件系统中的 B1
目录上方,形成以下的安排:
或者 C
可以直接挂载到 A
文件系统下的 A1
目录中:
完全可以只有一个大的根文件系统,而不需要创建其他文件系统。这种方法有一些缺点和一个优点。
-
不同的文件系统可以有不同的挂载选项。例如,根文件系统可以以只读方式挂载,这样用户就无法意外删除或编辑关键文件。将可由用户写入的文件系统(如
/home
)与其他文件系统分离,可以将它们挂载为 nosuid 。此选项可以防止文件系统上存储的可执行文件的_ suid_/guid 位生效,从而可能提高安全性。 -
FreeBSD 会根据文件系统的使用情况自动优化文件的布局。因此,包含许多频繁写入的小文件的文件系统将与包含较少且较大的文件的文件系统有所不同的优化方式。如果只有一个大文件系统,这种优化将失效。
-
如果断电,FreeBSD 的文件系统是健壮的。然而,在关键时刻断电仍然可能损坏文件系统的结构。通过将数据分散在多个文件系统上,系统更有可能重新启动,从而更容易根据需要进行备份恢复。
3.6.2. 磁盘分区
文件系统包含在 分区 中。使用多种分区方案将磁盘划分为分区;参见 [bsdinstall-part-manual]。较新的方案是 GPT ;旧的基于 BIOS 的计算机使用 MBR。GPT 支持将磁盘划分为具有大小、偏移和类型的分区。它支持大量的分区和分区类型,并且在可能的情况下推荐使用。GPT 分区使用磁盘名称加后缀,后缀为 p1
表示第一个分区,p2
表示第二个分区,依此类推。然而,MBR 仅支持少量的分区。在 FreeBSD 中,MBR 分区被称为 slices
。 Slices 可以用于不同的操作系统。 FreeBSD slices 使用 BSD 标签进行分区细分(参见 bsdlabel(8))。
Slice 号码遵循设备名称,以 s
为前缀,从 1 开始。因此,“da0s1”是第一个 SCSI 驱动器上的第一个 slice。一个磁盘上只能有四个物理 slice,但是在适当类型的物理切片内可以有逻辑 slice。这些扩展 slice 从 5 开始编号,因此“ada0s5”是第一个 SATA 磁盘上的第一个扩展 slice。这些设备由希望占用一个 slice 的文件系统使用。
每个 GPT 或 BSD 分区只能包含一个文件系统,这意味着文件系统通常通过其在文件系统层次结构中的典型挂载点或它们所包含的分区的名称来描述。
FreeBSD 还使用磁盘空间作为 交换空间 来提供 虚拟内存。这使得您的计算机可以表现得好像它拥有比实际更多的内存。当 FreeBSD 内存不足时,它将一些当前未使用的数据移动到交换空间,并在需要时将其移回(将其他数据移出)。这被称为 分页。
一些 BSD 分区与特定的约定相关联。
分区 |
惯例 |
---|---|
|
通常包含根文件系统。 |
|
通常包含交换空间。 |
|
通常与包含的 slice 大小相同。这样可以使需要在整个 slice 上工作的实用程序(例如坏块扫描器)能够在 |
|
分区 |
Slices 和“危险专用”物理驱动器包含 BSD 分区,这些分区用字母 a
到 h
表示。这个字母被附加到设备名称上,所以“ da0a”是第一个 da
驱动器上的 a
分区,该驱动器是“危险专用”的。“ada1s3e”是第二个 SATA 磁盘驱动器的第三个 slice 中的第五个分区。
最后,系统上的每个磁盘都有一个标识。磁盘名称以表示磁盘类型的代码开头,然后是一个数字,表示它是第几个磁盘。与分区和切片不同,磁盘编号从 0 开始。常见的代码列在 磁盘设备名称 中。
在引用 slice 中的分区时,请包括磁盘名称、s
、切片编号,然后是分区字母。示例见 示例磁盘、Slice 和分区名称 。 GPT 分区包括磁盘名称、p
,然后是分区编号。
磁盘的概念模型 展示了使用 MBR 分区的磁盘布局的概念模型。
在安装 FreeBSD 时,如果使用 MBR,请配置磁盘 slice,并在 slice 内创建用于 FreeBSD 的分区。如果使用 GPT ,请为每个文件系统配置分区。无论哪种情况,都要在每个分区中创建文件系统或交换空间,并决定每个文件系统将被挂载到哪里。有关操作分区的信息,请参阅 gpart(8) 。
驱动类型 | 驱动设备名称 |
---|---|
SATA 和 IDE 硬盘 |
|
SCSI 硬盘和 USB 存储设备 |
|
NVMe 存储 |
|
SATA 和 IDE CD-ROM 驱动器 |
|
SCSI CD-ROM 驱动器 |
|
软盘驱动器 |
|
SCSI 磁带驱动器 |
|
RAID 驱动器 |
例如,Adaptec® AdvancedRAID 的 |
名称 | 意义 |
---|---|
|
第一个 SATA 磁盘( |
|
第二个 SCSI 磁盘( |
这个图示展示了 FreeBSD 对系统上连接的第一个 SATA 硬盘的视图。假设该硬盘的容量为 250GB ,包含一个 80GB 的分区和一个 170GB 的分区(MS-DOS® 分区)。第一个分区包含一个 Windows® NTFS 文件系统,即 C:
,而第二个分区包含一个 FreeBSD 安装。这个示例的 FreeBSD 安装有四个数据分区和一个交换分区。
四个分区分别持有一个文件系统。分区 a
用于根文件系统,d
用于 /var/
,e
用于 /tmp/
,f
用于 /usr/
。分区字母 c
指的是整个 slice,因此不用于普通分区。
3.7. 挂载和卸载文件系统
文件系统最好被视为一棵树,以 /
作为根节点。根目录中的 /dev
、/usr
和其他目录是分支,它们可能有自己的分支,比如 /usr/local
等等。
将一些目录放在单独的文件系统上有各种原因。/var
包含了 log/
、spool/
以及各种类型的临时文件,因此可能会被填满。填满根文件系统是不明智的,所以将 /var
与 /
分离通常是可取的。
将某些目录树包含在其他文件系统中的另一个常见原因是它们将被放置在单独的物理磁盘上,或者是单独的虚拟磁盘,例如网络文件系统挂载,如 “网络文件系统( NFS )” 描述的,或者 CDROM 驱动器。
3.7.1. fstab 文件
在引导过程中(FreeBSD 引导过程),除了包含 noauto
条目的条目外,/etc/fstab
中列出的文件系统会自动挂载。该文件以以下格式包含条目:
device /mount-point fstype options dumpfreq passno
device
-
如 磁盘设备名称 中所解释的,现有设备名称。
mount-point
-
一个现有的目录,用于挂载文件系统。
fstype
-
传递给 mount(8) 的文件系统类型。默认的 FreeBSD 文件系统是
ufs
。 options
-
可以选择
rw
表示读写文件系统,或者ro
表示只读文件系统,后面可以添加其他可能需要的选项。常见的选项是noauto
,用于在启动序列期间通常不挂载的文件系统。其他选项可以在 mount(8) 中找到。 dumpfreq
-
dump(8) 使用此字段来确定哪些文件系统需要进行备份。如果该字段缺失,则默认为零值。
passno
-
确定在重新启动后,fsck(8) 应该按照什么顺序检查 UFS 文件系统。应该跳过的文件系统应该将其
passno
设置为零。根文件系统需要在其他所有文件系统之前进行检查,并且其passno
应该设置为一。其他文件系统的passno
应该设置为大于一的值。如果有多个文件系统具有相同的passno
,fsck(8) 将尝试在可能的情况下并行检查文件系统。
请参考 fstab(5) 以获取有关 /etc/fstab
格式及其选项的更多信息。
3.7.2. 使用 mount(8)
文件系统使用 mount(8) 进行挂载。最基本的语法如下:
# mount device mountpoint
在 /etc/fstab
中列出的文件系统也可以通过提供挂载点来挂载。
该命令提供了许多选项,这些选项在 mount(8) 中有描述。最常用的选项包括:
-a
-
挂载
/etc/fstab
中列出的所有文件系统,除了那些标记为“noauto”、被-t
标志排除的文件系统,以及已经挂载的文件系统。 -d
-
执行除实际挂载系统调用之外的所有操作。这个选项与
-v
标志一起使用非常有用,可以确定 mount(8) 实际上正在尝试做什么。 -f
-
强制挂载一个不干净的文件系统(危险操作),或者在将文件系统的挂载状态从读写改为只读时,撤销写访问权限。
-r
-
将文件系统挂载为只读模式。这与使用
-o ro
参数完全相同。 -t fstype
-
如果包含
-a
选项,则挂载指定的文件系统类型或仅挂载给定类型的文件系统。“ufs”是默认的文件系统类型。 -u
-
更新文件系统的挂载选项。
-v
-
提供详细信息。
-w
-
将文件系统挂载为读写模式。
可以将以下选项作为逗号分隔的列表传递给 -o
:
- nosuid
-
不要读取文件系统上的
setuid
或setgid
标志。这也是一个有用的安全选项。
3.8. 进程和守护进程
FreeBSD 是一个多任务操作系统。每个同时运行的程序被称为一个 进程。每个正在运行的命令都会启动至少一个新的进程,并且 FreeBSD 还会运行一些系统进程。
每个进程都由一个称为 进程 ID(PID)的数字唯一标识。与文件类似,每个进程都有一个所有者和组,并且所有者和组权限用于确定进程可以打开哪些文件和设备。大多数进程还有一个启动它们的父进程。例如,shell 是一个进程,shell 中启动的任何命令都是一个进程,其父进程是 shell 。例外情况是一个特殊的进程,称为 init(8),它始终是在启动时第一个启动的进程,其 PID 始终为 1
。
有些程序并不是设计成需要连续的用户输入,也不能在第一时间与终端断开连接。例如,Web 服务器响应 Web 请求,而不是用户输入。邮件服务器是另一种这种类型的应用程序。这些类型的程序被称为 守护进程(daemon)。术语 daemon 来自希腊神话,代表着一个既不善良也不邪恶的实体,它在不可见的情况下执行有用的任务。这就是为什么 BSD 吉祥物是一个看起来开心的带着运动鞋和叉子的 daemon。
有一个约定,即通常作为守护进程运行的程序的命名方式是以字母"d"结尾的。例如,BIND 是 Berkeley Internet Name Domain 的缩写,但实际执行的程序是 named
。Apache Web 服务器程序是 httpd
,线打印机排队守护进程是 lpd
。这只是一种命名约定。例如,Sendmail 应用程序的主邮件守护进程是 sendmail
,而不是 maild
。
3.8.1. 查看进程
要查看系统上运行的进程,请使用 ps(1) 或 top(1)。要显示当前正在运行的进程的静态列表,包括它们的进程 ID 、使用的内存量以及启动它们的命令,请使用 ps(1) 。要显示所有正在运行的进程,并每隔几秒更新一次显示,以便交互式地查看计算机正在做什么,请使用 top(1)。
默认情况下,ps(1) 只显示正在运行且由用户拥有的命令。例如:
% ps
输出应该类似于以下内容:
PID TT STAT TIME COMMAND 8203 0 Ss 0:00.59 /bin/csh 8895 0 R+ 0:00.00 ps
ps(1) 的输出被组织成多列。PID
列显示进程 ID。PID 从 1 开始分配,最大为 99999 ,然后重新从头开始分配。然而,如果 PID 已经被使用,它不会被重新分配。TT
列显示程序所在的 tty,STAT
列显示程序的状态。 TIME
是程序在 CPU 上运行的时间。这通常不是程序启动后经过的时间,因为大多数程序在需要在 CPU 上花费时间之前会花费很多时间等待事件发生。最后,COMMAND
是用于启动程序的命令。
有多种不同的选项可用于更改显示的信息。其中最有用的一组是 auxww
,其中 a
显示有关所有用户的所有运行进程的信息,u
显示进程所有者的用户名和内存使用情况,x
显示有关守护进程的信息,ww
使 ps(1) 显示每个进程的完整命令行,而不是在屏幕上显示过长时截断它。
top(1) 的输出类似:
% top
输出应该类似于以下内容:
last pid: 9609; load averages: 0.56, 0.45, 0.36 up 0+00:20:03 10:21:46 107 processes: 2 running, 104 sleeping, 1 zombie CPU: 6.2% user, 0.1% nice, 8.2% system, 0.4% interrupt, 85.1% idle Mem: 541M Active, 450M Inact, 1333M Wired, 4064K Cache, 1498M Free ARC: 992M Total, 377M MFU, 589M MRU, 250K Anon, 5280K Header, 21M Other Swap: 2048M Total, 2048M Free PID USERNAME THR PRI NICE SIZE RES STATE C TIME WCPU COMMAND 557 root 1 -21 r31 136M 42296K select 0 2:20 9.96% Xorg 8198 dru 2 52 0 449M 82736K select 3 0:08 5.96% kdeinit4 8311 dru 27 30 0 1150M 187M uwait 1 1:37 0.98% firefox 431 root 1 20 0 14268K 1728K select 0 0:06 0.98% moused 9551 dru 1 21 0 16600K 2660K CPU3 3 0:01 0.98% top 2357 dru 4 37 0 718M 141M select 0 0:21 0.00% kdeinit4 8705 dru 4 35 0 480M 98M select 2 0:20 0.00% kdeinit4 8076 dru 6 20 0 552M 113M uwait 0 0:12 0.00% soffice.bin 2623 root 1 30 10 12088K 1636K select 3 0:09 0.00% powerd 2338 dru 1 20 0 440M 84532K select 1 0:06 0.00% kwin 1427 dru 5 22 0 605M 86412K select 1 0:05 0.00% kdeinit4
输出分为两个部分。标题部分(前五或六行)显示了最后一个运行的进程的 PID ,系统负载平均值(衡量系统繁忙程度的指标),系统运行时间(自上次重启以来的时间)和当前时间。标题中的其他数字与正在运行的进程数量、已使用的内存和交换空间以及系统在不同 CPU 状态下花费的时间有关。如果加载了 ZFS 文件系统模块,ARC
行将显示有多少数据是从内存缓存中读取而不是从磁盘中读取的。
在标题下面是一系列列,其中包含与 ps(1) 输出类似的信息,例如 PID、用户名、CPU 时间和启动进程的命令。默认情况下,top(1) 还会显示进程占用的内存空间。这被分为两列:总大小和常驻大小。总大小是应用程序所需的内存量,常驻大小是它当前实际使用的内存量。
top(1) 每两秒自动更新显示。可以使用 -s
指定不同的间隔。
3.8.2. 杀死进程
与任何正在运行的进程或守护进程进行通信的一种方法是使用 kill(1) 发送一个 信号(signal)。有许多不同的信号;一些具有特定的含义,而其他信号在应用程序的文档中有描述。用户只能向自己拥有的进程发送信号,向他人的进程发送信号将导致权限被拒绝的错误。例外情况是 root
用户,他可以向任何进程发送信号。
操作系统也可以向进程发送信号。如果一个应用程序编写得很糟糕,试图访问它不应该访问的内存, FreeBSD 将向该进程发送“分段违规(Segmentation Violation)”信号(SIGSEGV
)。如果一个应用程序被编写成使用 alarm(3) 系统调用,在经过一段时间后被提醒,它将收到“闹钟(Alarm)”信号(SIGALRM
)。
有两个信号可以用来停止一个进程:SIGTERM
和 SIGKILL
。SIGTERM
是一种礼貌的方式来终止一个进程,因为进程可以读取该信号,关闭可能打开的任何日志文件,并尝试在关闭之前完成正在进行的操作。在某些情况下,如果进程正在执行无法中断的任务,它可能会忽略 SIGTERM
信号。
SIGKILL
无法被进程忽略。向一个进程发送 SIGKILL
通常会立即停止该进程。[1] 。
其他常用的信号包括 SIGHUP
、SIGUSR1
和 SIGUSR2
。由于这些是通用的信号,不同的应用程序会有不同的响应。
例如,在更改 Web 服务器的配置文件后,需要告诉 Web 服务器重新读取其配置。重新启动 httpd
将导致 Web 服务器短暂的停机时间。相反,发送 SIGHUP
信号给守护进程。请注意,不同的守护进程会有不同的行为,因此请参考守护进程的文档以确定是否使用 SIGHUP
可以达到所需的结果。
3.9. Shells
一个 shell 提供了一个命令行界面,用于与操作系统进行交互。 Shell 从输入通道接收命令并执行它们。许多 shell 提供了内置函数来帮助处理日常任务,如文件管理、文件通配符、命令行编辑、命令宏和环境变量。 FreeBSD 提供了几个 shell,包括 Bourne shell(sh(1))和扩展的 C shell(tcsh(1))。FreeBSD Ports Collection 中还提供了其他 shell,如 zsh
和 bash
。
使用的 shell 实际上是个人口味的问题。 C 程序员可能更喜欢类似 C 的 shell ,比如 tcsh(1) 。 Linux® 用户可能更喜欢 bash
。每个 shell 都有独特的特性,可能适用或不适用于用户首选的工作环境,这就是为什么可以选择使用哪个 shell 的原因。
一个常见的 shell 功能是文件名补全。当用户输入命令或文件名的前几个字母并按下 Tab 键时, shell 会自动完成命令或文件名的剩余部分。假设有两个文件名分别为 foobar
和 football
。要删除 foobar
,用户可以输入 rm foo
并按下 Tab 键来完成文件名的补全。
但是 Shell 只显示 rm foo
。由于 foobar
和 football
都以 foo
开头,它无法完成文件名。一些 Shell 会发出哔哔声或显示所有匹配的选项。用户必须输入更多字符来识别所需的文件名。输入一个 t
并再次按下 Tab 就足够让 Shell 确定所需的文件名并填充剩下的部分。
shell 的另一个特性是使用环境变量。环境变量是存储在 shell 环境中的键值对。任何由 shell 调用的程序都可以读取这个环境,并因此包含了许多程序配置。 常见的环境变量 提供了常见环境变量及其含义的列表。请注意,环境变量的名称始终为大写。
变量 |
描述 |
---|---|
|
当前登录用户的名称。 |
|
以冒号分隔的目录列表,用于搜索二进制文件。 |
|
如果可用,连接到的 Xorg 显示器的网络名称。 |
|
当前的 Shell 。 |
|
用户终端的类型名称。用于确定终端的功能。 |
|
终端转义码的数据库条目,用于执行各种终端功能。 |
|
操作系统的类型。 |
|
系统的 CPU 架构。 |
|
用户首选的文本编辑器。 |
|
用户首选的逐页查看文本的实用工具。 |
|
以冒号分隔的目录列表,用于搜索手册页。 |
在不同的 shell 中设置环境变量的方法是不同的。在 tcsh(1) 和 csh(1) 中,使用 setenv
来设置环境变量。在 sh(1) 和 bash
中,使用 export
来设置当前的环境变量。以下示例将默认的 EDITOR
设置为 /usr/local/bin/emacs
,适用于 tcsh(1) shell。
% setenv EDITOR /usr/local/bin/emacs
bash
的等效命令是:
% export EDITOR="/usr/local/bin/emacs"
为了展开环境变量以查看其当前设置,在命令行中在其名称前面键入 $
字符。例如,echo $TERM
会显示当前的 $TERM
设置。
Shell 将特殊字符,称为元字符,视为数据的特殊表示。最常见的元字符是 *
,它表示文件名中的任意数量的字符。元字符可以用于执行文件名通配符匹配。例如,echo *
等同于 ls
,因为 shell 会将与 *
匹配的所有文件取出,并在命令行上列出它们。
为了防止 shell 解释特殊字符,可以通过在特殊字符前加上反斜杠(\
)来将其从 shell 中转义。例如, echo $TERM
会打印终端设置,而 echo \$TERM
会直接打印字符串 $TERM
。
3.9.1. 更改 Shell
永久更改默认 shell 的最简单方法是使用 chsh
命令。运行此命令将打开在 EDITOR
环境变量中配置的编辑器,默认设置为 vi(1)。将 Shell:
行更改为新 shell 的完整路径。
或者,使用 chsh -s
命令可以在不打开编辑器的情况下设置指定的 shell。例如,要将 shell 更改为 bash
:
% chsh -s /usr/local/bin/bash
在提示符处输入您的密码,然后按下 Return 键来更改您的 shell。注销并重新登录以开始使用新的 shell。
新的 shell 必须存在于
然后,重新运行 chsh(1)。 |
3.9.2. 高级 Shell 技巧
UNIX® shell 不仅仅是一个命令解释器,它还是一个强大的工具,允许用户执行命令、重定向输出、重定向输入以及链式组合命令,以提高最终命令的输出。当这种功能与内置命令结合使用时,用户可以获得一个可以最大化效率的环境。
Shell 重定向是将命令的输出或输入发送到另一个命令或文件的操作。例如,要将 ls(1) 命令的输出捕获到文件中,可以使用重定向操作:
% ls > directory_listing.txt
目录内容现在将会列在 directory_listing.txt
中。一些命令可以用来读取输入,比如 sort(1) 。要对这个列表进行排序,可以重定向输入:
% sort < directory_listing.txt
输入将被排序并显示在屏幕上。要将该输入重定向到另一个文件,可以通过混合方向来重定向 sort(1) 的输出。
% sort < directory_listing.txt > sorted.txt
在所有之前的示例中,命令都是使用文件描述符进行重定向。每个 UNIX® 系统都有文件描述符,包括标准输入 (stdin)、标准输出 (stdout) 和标准错误 (stderr)。每个文件描述符都有其用途,其中输入可以是键盘或鼠标,提供输入的设备。输出可以是屏幕或打印机上的纸张。而错误则是用于诊断或错误消息的任何内容。这三个都被视为基于 I/O 的文件描述符,有时也被称为流。
通过使用这些描述符, Shell 允许输出和输入在各个命令之间传递,并可以重定向到文件或从文件中读取。另一种重定向的方法是管道操作符。
UNIX® 管道操作符“|”允许将一个命令的输出直接传递或定向到另一个程序。基本上,管道允许将一个命令的标准输出作为另一个命令的标准输入传递,例如:
% cat directory_listing.txt | sort | less
在这个例子中,directory_listing.txt
的内容将被排序,并且输出将传递给 less(1) 。这使得用户可以按照自己的节奏滚动输出,并防止其滚动到屏幕外。
3.10. 文本编辑器
大多数 FreeBSD 的配置是通过编辑文本文件来完成的,因此熟悉文本编辑器是一个好主意。FreeBSD 自带了一些基本系统的文本编辑器,还有更多的编辑器可以在 Ports Collection 中找到。
一个简单的学习编辑器是 ee(1) ,它代表着 easy editor(简易编辑器)。要启动这个编辑器,输入 ee filename
,其中 filename 是要编辑的文件名。一旦进入编辑器,所有用于操作编辑器功能的命令都列在显示屏的顶部。插入符号(^
)代表 Ctrl,所以 ^e
扩展为 Ctrl+e。要离开 ee(1),按下 Esc,然后从主菜单中选择“离开编辑器”选项。如果文件已被修改,编辑器将提示保存任何更改。
FreeBSD 还配备了更强大的文本编辑器,例如 vi(1),作为基本系统的一部分。其他编辑器,如 editors/emacs 和 editors/vim,是 FreeBSD Ports Collection 的一部分。这些编辑器提供了更多的功能,但学习起来更加复杂。学习使用像 vim 或 Emacs 这样更强大的编辑器可以在长期来看节省更多的时间。
许多修改文件或需要输入文本的应用程序会自动打开一个文本编辑器。要更改默认的编辑器,请按照 Shells 中描述的方式设置 EDITOR
环境变量。
3.11. 设备和设备节点
设备是系统中主要用于硬件相关活动的术语,包括磁盘、打印机、显卡和键盘等。当 FreeBSD 启动时,大部分引导消息都是关于检测到的设备。引导消息的副本保存在 /var/run/dmesg.boot
中。
每个设备都有一个设备名称和编号。例如, ada0
表示第一个 SATA 硬盘,而 kbd0
表示键盘。
在 FreeBSD 中,大多数设备必须通过称为设备节点的特殊文件进行访问,这些文件位于 /dev
目录中。
3.12. 手册页
FreeBSD 上最全面的文档是以手册页的形式存在的。系统上几乎每个程序都附带有一个简短的参考手册,解释其基本操作和可用参数。可以使用 man
命令查看这些手册。
% man command
其中 command 是要了解的命令的名称。例如,要了解有关 ls(1) 的更多信息,请输入:
% man ls
手册页被分为不同的章节,代表不同的主题类型。在 FreeBSD 中,有以下几个章节可用:
-
用户命令。
-
系统调用和错误编号。
-
C 库中的函数。
-
设备驱动程序。
-
文件格式。
-
游戏和其他娱乐活动。
-
杂项信息。
-
系统维护和操作命令。
-
系统内核接口。
在某些情况下,同一个主题可能会出现在在线手册的多个部分中。例如,有一个 chmod
用户命令和一个 chmod()
系统调用。要告诉 man(1) 显示哪个部分,需要指定部分号码:
% man 1 chmod
如果不知道手册页的名称,请使用 man -k
在手册页描述中搜索关键字:
% man -k mail
该命令显示具有关键字“mail”在其描述中的命令列表。这相当于使用 apropos(1) 命令。
要阅读 /usr/sbin
目录下所有命令的描述,请输入:
% cd /usr/sbin
% man -f * | more
或者
% cd /usr/sbin
% whatis * |more
3.12.1. GNU Info 文件
FreeBSD 包含了由自由软件基金会(FSF)制作的多个应用程序和实用工具。除了手册页,这些程序还可能包括称为 info
文件的超文本文档。可以使用 info(1) 命令或者如果安装了 editors/emacs ,可以使用 emacs 的 info 模式来查看这些文件。
要使用 info(1),请输入:
% info
要进行简要介绍,请输入 h
。要查看快速命令参考,请输入 ?
。
上次修改时间: September 18, 2024 by fiercex