CentOS-快速启动指南-全-

CentOS 快速启动指南(全)

原文:annas-archive.org/md5/7e67f10f1902b17236cfa846256a5249

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

本书将提供一个通过 CentOS 7 学习 Linux 必备技能的介绍。它描述了 Linux 系统的组织结构,并介绍了关键的命令行概念,读者可以自行练习。它引导读者执行基本的系统管理任务和日常操作。

如今,Linux 无处不在。它是大多数技术创新的核心,驱动着从最小的智能设备到全球最大的超级计算机等各种设备。Linux 内核开发至今仍是全球最大的合作项目。读者将学习 Linux 和开放源代码技术在现代计算环境中的基础知识。本书将以简明且实用的方式向用户介绍 CentOS 7。书中大多数命令行都配有图示,以帮助更好地理解。

阅读完本书后,你将对使用命令行操作 Linux 有扎实的理解。你将学习如何管理运行 CentOS 7 或类似操作系统(如 RHEL 7、Scientific Linux 和 Oracle Linux)的系统的核心系统管理技能。阅读完本书后,你将能够执行安装、建立网络连接、管理用户和进程、修改文件权限、使用命令行管理文本文件,并实现基本的安全管理。

本书适合谁阅读

本书适合任何希望在其环境中将 Linux 用作服务器或桌面计算机的个人。无论你是开发人员、新手系统管理员,还是没有 Linux 管理背景的技术爱好者,本书将帮助你以 CentOS 7 为基础,开始你的 Linux 学习之旅。

尽管本书是为初学者编写的 Linux 使用指南,但有经验的 Linux 用户也能从每一章中获得一些收获。你不需要任何 Linux 命令行的工作经验就能阅读本书。大多数 Linux 新手发现使用命令行很困难,偶尔也会对选择从哪个 Linux 发行版开始感到困惑。你将使用 CentOS 7 学习 Linux,它是基于 RHEL 7 的最受欢迎和最稳定的 Linux 发行版之一。

本书的一些关键特点如下:

  • 阅读本书前无需任何 Linux 环境经验

  • 读者将会熟悉一个流行且稳定的 Red Hat 企业版 Linux 发行版

  • 内容简明扼要,全面覆盖重要工具

本书以一种易于理解的方式编写,任何对操作系统有基本了解的计算机用户都可以开始使用它。唯一的前提是你有一台足够好的硬件,可以安装 CentOS 7 并练习书中的命令。

如何充分利用本书

一如既往,我们已尽最大努力确保本书内容符合用户需求。本书中涉及的所有命令行均基于 CentOS 7。您可以使用任何小版本的 CentOS 7,从 CentOS 7.1 到 CentOS 7.6。本书唯一的要求是使用 CentOS 7 操作系统。然而,对于初学者,建议在任何桌面虚拟化应用程序中安装并练习 CentOS 7,例如 VirtualBox 和 VMWare Workstation。

对于希望使用虚拟环境的 Windows 和 macOS 用户,他们可以使用 VMWare 或 VirtualBox 设置 CentOS 7 并执行给定的命令行示例。对于 Linux 新手,本书第一章 CentOS 7 入门 中详细介绍了 CentOS 7 的安装方法。

使用的约定

本书中使用了许多文本约定。

CodeInText:表示文本中的代码字、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账户名。例如:“例如,mkdir 使用中的 DIRECTORY.. 表示我们需要插入我们希望与 mkdir 命令一起使用的目录名。”

任何命令行输入或输出如下所示:

$ mkdir -p -v demo/linux/centos

粗体:表示新术语、重要单词或屏幕上显示的单词。例如,菜单或对话框中的单词会像这样出现在文本中。举个例子:“之后,‘开始安装’按钮将被启用。”

警告或重要说明以这种方式显示。

小贴士和技巧以这种方式出现。

联系我们

我们始终欢迎读者的反馈。

一般反馈:如果您对本书的任何部分有疑问,请在邮件主题中提及书名,并通过 customercare@packtpub.com 给我们发送邮件。

勘误:虽然我们已尽一切努力确保内容的准确性,但错误仍然会发生。如果您在本书中发现错误,我们将非常感激您能向我们报告。请访问 www.packt.com/submit-errata,选择您的书籍,点击“勘误提交表单”链接,并填写详细信息。

盗版:如果您在互联网上发现我们作品的任何非法复制品,我们将非常感激您提供该位置地址或网站名称。请通过 copyright@packt.com 与我们联系,并附上相关材料的链接。

如果您有兴趣成为作者:如果您在某个主题方面有专长,并且有兴趣写作或参与书籍创作,请访问 authors.packtpub.com。

评价

请留下评论。读完并使用本书后,为什么不在您购买本书的网站上留下评论呢?潜在读者可以查看并参考您公正的意见做出购买决策,我们 Packt 可以了解您对我们产品的看法,而我们的作者也能看到您对他们书籍的反馈。谢谢!

如需了解更多关于 Packt 的信息,请访问 packt.com。

第一章:CentOS 7 入门

社区企业操作系统,通常称为CentOS,是一个快速、稳定、开源的企业级 Linux 发行版,广泛应用于笔记本、台式机和服务器。它源自Red Hat Enterprise Linux(RHEL)的源代码,后者由 CentOS 社区开发和维护。所有与 Red Hat Inc. 相关的专有内容都被从 CentOS 软件包中移除,之后这些软件包会重新编译,加入 CentOS 社区的资源,如标志等。CentOS 7 是 RHEL 7 的完全复制版,但它免费提供并由社区支持和更新。CentOS 项目现在由 Red Hat Inc. 官方赞助,最适用于那些不强求操作系统商业支持的环境。

本章将为你提供一个安装 CentOS 7 到你计算机的详细指南。安装完成后,我们将介绍 Linux 的命令行控制台,以便你使用Bash(即Bourne Again Shell)。本章将教你如何设置环境,以便执行本书后续章节中的所有练习。

本章将涵盖以下内容:

  • 准备安装 CentOS 7

  • 执行手动安装

  • 使用控制台访问命令行

  • 介绍 Bash Shell

  • Bash shell 和命令执行

准备安装 CentOS 7

CentOS 社区发布了最新的操作系统版本,名为 CentOS 7.6-1810,其中 7.6 源自 RHEL 7.6,1810 表示其发布日期(2018 年 10 月)。CentOS 7.6 可以安装在物理或虚拟硬件上。你可以根据你的环境使用任何主流的桌面虚拟化软件,如 Oracle VirtualBox(www.virtualbox.org/wiki/Downloads)或 VMWare Workstation(www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html)。我选择的桌面虚拟化软件是 VirtualBox,因为它是免费的、开源的,且易于使用。你还需要一个正常工作的互联网连接,以便从社区下载页面下载 CentOS 镜像。

使用 Linux 作为基础操作系统的用户也可以使用 KVM 进行虚拟化。

获取合适的硬件

对于 CentOS 7.6 的最小安装,必须满足以下硬件要求:

  • 512 MB 内存

  • 4 GB 硬盘空间

  • 网络适配器

然而,为了练习本书中描述的所有练习,我们建议满足以下硬件要求:

  • 支持 64 位架构

  • 1 GB 内存

  • 10 GB 硬盘空间

  • DVD 驱动器或 USB 存储棒

  • 网络适配器

获取软件

有多种方法可以获取执行本书中所有练习所需的软件。然而,最简单、最灵活的方法是从 CentOS 网站下载 iso 文件,并将其刻录到 DVD 上,或使用 CentOS 创建可启动的 USB 驱动器。然后,如果您使用的是虚拟机,请使用 ISO DVD 镜像启动您的 PC。如果您在物理系统上安装,则使用可启动的 USB 驱动器或刻录的 CentOS DVD 进行安装。

使用以下链接下载 CentOS 7.6(64 位)ISO 镜像文件:

centos.mirror.net.in/centos/7.6.1810/isos/x86_64/CentOS-7-x86_64-DVD-1810.iso

您可以从 CentOS 网站下载镜像文件的 MD5 和 SHA1 哈希值。下载的镜像文件的哈希值应与 CentOS 网站上发布的哈希值相同。

完成服务器设置细节

一旦您有了合适的硬件和软件来进行 CentOS 安装,您应该决定在安装过程中需要指定的基本设置参数。下表列出了我们在本章描述的 CentOS 7.6 服务器安装中使用的详细信息:

设置参数 示例值
IP 地址 192.168.0.100
子网掩码 255.255.255.0
主机名 Server.example.com
根密码 Linux@12345
用户名 Student
用户密码 Student@12345

执行手动安装

如今,安装 CentOS 最快、最简单的方法是使用可启动的 USB 驱动器;然而,在我们的案例中,我选择使用带有虚拟机的 DVD ISO 镜像。首先,我们需要使用 DVD 启动计算机系统/虚拟机。启动 DVD 后,您将看到一个酷炫的 CentOS 屏幕,显示基本的安装选项、媒体测试和故障排除选项。一旦您的系统/虚拟机成功启动了 CentOS 7 的可启动 DVD,请按照以下步骤在系统上安装 CentOS:

  1. 我们必须选择安装 CentOS 7选项并按Enter键,如下图所示。这将启动图形化安装程序,并询问要在安装过程中使用的语言:

  1. 现在,您将看到一个欢迎使用 CentOS 7屏幕,提示您选择语言和键盘设置。选择您的语言和键盘设置,然后点击继续按钮,如下图所示。在我的案例中,我选择了英语:

  1. 接下来,您将看到一个安装摘要屏幕。在此屏幕上,您可以指定您想要用于三个不同部分及其子部分的设置,如下图所示:

在此屏幕上,只要安装总结屏幕中显示的任何部分或子部分还未完成,开始安装按钮将保持禁用。只有当屏幕上显示的所有部分和子部分都完成且符合最小安装要求时,开始安装按钮才会启用。

默认情况下,安装程序会自动进行硬盘分区。如果我们想使用默认的布局,那么我们必须点击安装目标,然后在下一个屏幕上点击“完成”按钮,批准我们要用于自动分区的磁盘设备。之后,“开始安装”按钮将被启用,我们可以进行最小配置的 CentOS 安装,如下图所示:

CentOS 7 的最小安装没有图形界面——它只安装了一些基本的包,命令行界面中功能有限。

  1. 如果你是新手并且希望使用带有图形用户界面(GUI)的 CentOS 7,请按照这些安装说明进行操作。在这个步骤中,我们将学习如何使用 CentOS,并修改在安装过程中需要配置的某些选项。安装总结屏幕包含三个部分,如下所示:

    • 本地化

    • 软件

    • 系统

这三个部分的说明如下:

  • 本地化:该部分还包含以下三个子部分供配置:

    • 日期和时间

    • 键盘

    • 语言支持

或者这三个选项中,日期和时间子部分通常需要配置。其他两个选项我们已经在之前的步骤中配置过了。

在日期和时间选项中,通过点击世界地图上的位置选择你所在的时区。你还可以从这个窗口中配置当前的日期和时间,如下图所示:

我们将键盘和语言支持设置保持为默认,接着进入下一个需要配置的部分——在这个案例中是软件。

  • 软件:该部分还包含两个子部分供配置:

    • 安装源

    • 软件选择

在“软件”部分,我们将安装源设置为默认的本地媒体(DVD-ROM),如下截图所示:

下一个需要配置的子部分是软件选择。这是安装过程中的一个重要部分。点击此选项,你将看到下面截图所示的界面。在这里,你可以选择默认的基础环境和可用的附加组件。在我们的演示中,我们将安装 GNOME 桌面基础环境,并添加四个附加组件:GNOME 应用程序、办公套件与生产力工具、开发工具和系统管理工具,如下图所示:

  • 系统:此部分进一步包含四个子部分以进行配置:

    • 安装目标

    • KDUMP

    • 网络与主机名

    • 安全策略

在本节中,我们将 KDUMP 和安全策略子部分保持为默认参数,并按照以下方式配置其余两个子部分:

在安装目标子部分中,我们指定了 CentOS 的安装位置。默认情况下选择了自动分区,但我们可以根据自己的需求创建自定义的手动分区方案。作为最低标准,我们将创建以下三个分区:

    • 启动分区:此分区存储可引导文件,如内核镜像等。

    • 交换分区:用于将文件和程序在内存和磁盘之间交换。其大小通常为内存的两倍。

    • 根(/) 分区:包含 Linux 文件系统。

以下截图显示了点击的位置,以创建手动分区:

  1. 选择要安装操作系统的设备,并选择“我将配置分区”。最后,点击“完成”按钮以继续按照以下截图所示创建多个分区:

  1. 现在,我们在分区表中创建至少三个分区(boot、swap和/)。在我的情况下,我将文件系统设置为 xfs,并为boot和/分区选择了标准分区类型。对于swap分区,文件系统类型设置为swap,如下图所示:

  1. 接下来,按下“完成”后,您将看到“更改摘要”对话框。点击“接受更改”按钮,开始在磁盘上创建我们在分区表中指定的分区,如下图所示:

  1. 网络与主机名:在安装总结的最后部分,我们将配置网络。您可以保持默认设置,从 DHCP 服务器获取 IP 地址,或者点击“网络与主机名”手动设置网络。在对话框中,点击 IPv4 设置标签,然后从下拉菜单中选择“手动”作为方法,并指定私有 IP 地址,如下图所示:

在网络与主机名设置中,将网络连接状态从关闭更改为打开,如下图所示:

  1. 现在,所有的安装总结部分已经按要求配置,开始安装按钮已启用。点击“开始安装”按钮以启动安装过程,如下图所示:

  1. 接下来,屏幕提示输入用户设置。这里,我们首先点击 Root Password 并将密码设置为 Linux@12345。

  2. 接下来,我们点击 CREATE USER 来创建一个用户。在 Full name 和 User name 字段中,输入 student,并将密码设置为 Student@12345。在这里,我们还需要点击 Done 按钮两次以确认密码,如下图所示:

  1. 在安装过程中,喝杯咖啡吧。安装完成后,移除任何安装介质(这些指示仅适用于 DVD 方法),然后点击 Reboot 按钮,如下图所示:

  1. 系统重新启动后,我们将看到 INITIAL SETUP 屏幕,在这里我们必须接受 EULA 协议后才能登录系统。此时,我们点击 LICENSE INFORMATION 来接受许可协议,如下图所示:

  1. 一旦接受了许可协议,FINISH CONFIGURATION 按钮将变为可用。点击它以进入登录屏幕。

  2. 在登录屏幕上,点击 student 用户名并输入密码 Student@12345,如下图所示:

  1. 成功登录后,你将看到欢迎屏幕,该屏幕仅在用户首次登录时显示。点击 Next 按钮以进入桌面。

  2. 恭喜!你已经成功在你的计算机系统或虚拟机上安装了最新版本的 CentOS 7。你可以探索你的新 CentOS 7 环境并执行其他任务,例如更新系统或安装其他日常操作所需的软件。要关闭系统,点击桌面右上角。你将看到一个下拉菜单;从中可以点击 Shut down,如下图所示:

至此,安装过程已完成。在接下来的章节中,我们将学习如何访问命令行控制台。

使用控制台访问命令行

使用 CentOS 时,系统管理或应用程序开发任务是通过 命令行界面 (CLI),例如 Bash shell,或通过图形界面,如 GNOME、KDE 等来完成的。在本节中,我们将学习如何在 Linux 控制台的 Bash shell 中输入命令。

启动终端

当你以 CLI 模式登录 Linux 系统或打开终端时,它会显示一个字符串,等待用户输入(一个命令)。这被称为 shell 提示符。

要在图形界面环境中访问 shell 提示符,必须启动一个终端应用程序,例如 GNOME 终端。有多种方式可以启动终端。访问终端的最常用方式如下:

  • 选择应用程序 | 系统工具 | 终端

  • 在终端上右键单击任意位置,然后从弹出的上下文菜单中选择“在终端中打开”

  • 在活动概览中,选择终端

如果你以普通用户身份启动了终端应用程序,则默认的提示符以 $ 字符结尾,如下图所示:

普通的 Shell 提示符列出以下三项内容:

  • 当前用户的登录名

  • 机器的短主机名,也称为机器名称

  • 当前工作目录的名称

Shell 提示符中的波浪线(~)代表用户的主目录。我们将在接下来的章节中进一步了解这一点。

如果你以 root 用户身份启动或切换到 Shell,也就是被称为超级用户或管理员,则提示符以 # 字符结尾,如下图所示:

CentOS 7 的默认 Shell 是 Bash,它提供了脚本功能,用于自动化重复任务。任何 Shell 的主要功能是解释用户在提示符下输入的命令,并为启动任何其他程序提供平台。

Unix 发行版的默认 Shell 通常设置为 Bourne Shell。它类似于 Microsoft Windows 的命令提示符应用程序cmd.exe。从 Windows 7 和 Windows Server 2008 R2 开始,包含了 Microsoft PowerShell,它在功能上与 Bash 非常相似。

有两种方法可以访问 Shell。第一种方法是通过终端。当你以没有图形界面(如文本安装)的方式安装 Linux 时,这可以是 Linux 机器的物理控制台,包含一个用于输入的键盘和一个显示输出的显示器。

第二种方法是通过虚拟控制台中的 Shell。Linux 机器的物理控制台支持多个虚拟控制台,这些虚拟控制台作为独立的终端,拥有独立的登录会话。如果安装了图形用户界面(GUI),那么第一个虚拟控制台就是 CentOS/RHEL 中的图形界面。除了第一个图形环境,虚拟控制台还提供五个纯文本环境,你可以使用这些环境访问登录 Shell。Ctrl + Alt + (F2 到 F6) 是基于文本的,而 Ctrl + Alt + F1 是图形桌面。

命令行语法和结构

在 Shell 提示符中输入的任何命令都可以分为三部分:

部分 描述
命令 要执行的应用程序的名称
选项 这会修改命令的行为;选项通常以一个或两个短划线开头
参数 这些通常指示命令应用的目标

一个命令可以由一个或多个选项组成,并且可以接受一个或多个参数,这取决于它的语法。理解命令的语法将告诉你它可以接受哪些选项和参数,以及它们的顺序。要查看命令的语法,我们可以使用--help选项或查看手册页。mkdir命令及其选项的用法如下图所示:

最初,你可能会觉得--help选项的输出有些困惑。然而,一旦你理解了语法中使用的基本约定,它就会变得简单得多,接下来会讨论这些约定:

  • 方括号[ ]包含可选项。例如,执行mkdir命令时,不强制要求使用任何选项,以下命令行中展示了这一点:
$ mkdir mydirectory
  • 省略号…表示某种类型的多个项。例如,我们可以将多个选项,如-m和-p或-v,与mkdir命令一起使用,如以下命令行所示:
$ mkdir -p -v demo/linux/centos
  • 斜体括号<>中的文本表示变量数据。有时,变量数据也用大写字母书写。例如,mkdir中的DIRECTORY..表示我们必须插入希望与mkdir命令一起使用的目录名称。

  • 用管道符号(|)分隔的多个项目,意味着只能指定其中一个项目。

退出 shell

当你使用完 shell 并且想要结束会话时,有多种退出方法。以下是一些常用的退出 shell 选项:

  • 在控制台上随时输入exit命令可以终止当前会话。

  • 按下Ctrl + D键组合也是一个常用的快捷方式,用于终止当前会话。

介绍 Bash shell

GNU Bash 主要是一个解释用户在提示符下输入的命令的程序。正如我们在之前的命令行语法与结构部分所学到的,每个由用户输入的命令可以包含三部分:

  • 命令

  • 选项(以-或--开头)

  • 参数

在 shell 中输入的每个单词与其他单词之间用空格分隔。命令是我们系统中安装的各种应用程序的名称,每个命令都有自己的选项和参数。

当你想执行在提示符处输入的命令时,按下Enter键。按下Enter键后,命令的输出会显示在 shell 上,紧接着再次显示提示符,如以下截图所示:

每个命令都是在单独的一行上输入的;然而,如果你愿意,你可以在一行中输入多个命令,使用分号(;)作为命令分隔符。

shell 执行的各种功能包括以下内容:

  • 它提供了用户与操作系统之间的接口

  • 它是用户执行命令和其他程序的一种方式

  • 它充当命令提示符下输入命令的命令行解释器

  • Shell 还通过读取来自特定文本文件的命令(称为 Shell 脚本)来实现任务自动化

  • Shell 为在操作系统上运行的用户和程序提供了一个环境

每个 Linux 发行版上都安装了多种类型的 shell,它们之间的功能略有不同。Bourne shell(sh)是最原始的,而 Bash shell 是最先进的。以下表格列出了这些 shell 之间的差异:

特性 Bourne Korn C Tcsh Bash
后台处理 是 是 是 是 是
命令历史 否 是 是 是 是
I/O 重定向 是 是 是 是 是
Shell 脚本 是 是 是 是 是
命令别名 否 是 是 是 是
文件名补全 否 是 否 是 是
命令补全 否 否 否 是 是
命令行编辑 否 是 否 是 是
作业控制 否 是 是 是 是

Bash shell 和命令执行

在本节中,我们将学习 Bash shell 的不同功能,通过这些功能,你可以减少错误并提高在终端上工作的速度。

Tab 补全

Linux Shell 语法对大小写和空格敏感,因此输入错误是任何初学者的首要障碍。然而,如果初学者采用 Tab 补全功能,就能显著减少输入错误,使得操作变得非常简便流畅。

Tab 补全功能可以在命令提示符下输入足够的字符来唯一标识命令名或文件名时自动完成。如果输入的字符不唯一,按 Tab 键两次会显示所有可以以已输入字符开始的命令。以下截图展示了使用 Tab 键进行命令补全的示例:

Tab 补全功能可以在输入文件名或路径名作为命令的参数时自动补全。按下 Tab 键一次,如果文件名或路径名唯一,就会自动完成;否则,再按一次 Tab 键会列出所有可能的文件名或路径名组合。之后,你可以输入额外的字符来使名称或路径唯一,再次按 Tab 键即可完成命令行。以下截图展示了使用 Tab 键进行路径和文件名补全的示例:

命令行编辑快捷键

Bash 具有非常实用的命令行编辑功能,可以提高你在终端工作时的生产力。它使用户能够使用一些快捷命令在命令提示符上移动或删除字符。

以下表格列出了 Bash 中最有用的命令行快捷键:

快捷键 描述
移动光标
Ctrl + A 将光标移动到命令行的开头
Ctrl + E 将光标移动到命令行的末尾
Ctrl + Left arrow 将光标移动到命令行中当前单词的开始位置
Ctrl + Right arrow 将光标移动到命令行中下一个单词的开始位置
删除字符
Ctrl + U 删除从当前光标位置到命令行开头的所有字符
Ctrl + K 删除从当前光标位置到命令行末尾的所有字符
Ctrl + W 从当前光标位置删除命令行中的最后一个单词
Ctrl + L 清屏(你也可以输入 clear 命令)
修改终端窗口大小
Ctrl + + 增加终端窗口的大小
Ctrl - - 减小终端窗口的大小

history 命令

history 命令用于显示之前执行过的命令列表,每条命令前都有一个命令编号,表示其执行的顺序,如下图所示:

感叹号字符(!)是 Bash 中的元字符,用于从历史列表中扩展先前执行的命令。

以下表格列出了对初学者非常有用的各种 history 命令:

命令 描述
!<number> 展开为与指定编号匹配的命令
!<string> 展开为历史列表中以指定字符串开头的最新命令
history -d <number> 用于从历史中删除指定编号的命令
history -c 清空历史列表
Ctrl + R 在命令历史列表中搜索模式,并在找到时执行最匹配的命令

以下截图显示了 history 命令的用法:

除了已经列出的选项外,我们还可以使用箭头键在 shell 历史中的上一条和下一条命令之间进行导航。上箭头键会显示历史列表中上一次执行的命令,下箭头键则会显示历史列表中的下一条命令。

命令别名

alias 命令用于为常用命令创建别名或昵称。它通过为长命令或命令组合提供别名名称,从而简化了管理过程。

列出当前的别名

要列出当前为你的 shell 配置的别名,只需在提示符下输入 alias 命令,不带任何参数,如下命令行所示:

$ alias

设置别名

使用以下语法可以为 exit 命令设置别名 x。因此,在设置此别名后,每当你想退出终端时,只需在提示符下输入 x:

$ alias x="exit"
$ alias c="clear"

移除一个 alias

要移除一个 alias,可以使用 unalias 命令。例如,要移除之前设置的 alias,我们可以按如下方式使用 unalias 命令:

$ unalias x

alias 命令将只为当前会话设置别名。如果你想为任何命令设置永久的别名,你需要在 /etc/bashrc 文件中添加相应条目以进行全局修改。如果想要设置用户特定的修改,则应将该条目添加到存储在用户主目录中的 .bashrc 文件中。

总结

在本章中,我们开始了 CentOS 7 的学习之旅。首先,我们从安装过程开始,接着介绍了 Bash shell 及命令行语法和结构。然后,我们通过 Tab 键、命令行快捷方式、history 和 aliases,掌握了如何通过更少的敲击从 shell 中运行命令的基本功能。

在下一章中,我们将继续深入探索 CentOS 7,了解 Linux 文件系统层级结构以及其他基本内容。

第二章:命令行和文件系统导航

在本章中,我们的目标是确定 CentOS 7 文件系统中重要目录的作用,并学习各种基本的命令行技能。当我们在命令行工作时,必须清晰地了解文件系统的层次结构、布局和组织方式。我们将通过 CentOS 7 中存在的各种文档,包括 man 页面、info 页面、help命令选项等来了解。随后,我们将学习各种文件系统导航和管理命令,包括更改目录、复制、移动、重命名文件等。最后,我们将学习归档和压缩文件,这在创建备份时非常常见。

在本章中,我们将覆盖以下内容:

  • 理解 CentOS 7 的文件系统层次结构

  • 使用 man 页面和help命令

  • 管理带有路径扩展的文件名

  • 使用命令行工具管理文件

  • 管理档案和压缩文件

理解 CentOS 7 的文件系统层次结构

我们可以将文件系统比作冰箱,或者任何其他有多个货架用于存储不同物品的储物柜。这些货架或隔间帮助我们根据物品的形状、大小、类型等特征,在冰箱中组织食品。同样的类比适用于文件系统,它是存储和组织数据及文件集合的缩影,以便人类可以使用。

文件系统以倒根树的设计方式组织,/(一个斜杠,发音为根)是文件系统的根,其下方是其余的目录和子目录,如下图所示:

CentOS 7 中的重要文件系统目录

这种文件系统层次结构的布局在 Linux 文件系统层次结构标准中进行了描述。

在这里,/表示两种含义:

  • 文件系统层次结构顶部的根目录。

  • 它也作为目录分隔符,用来将一个目录与另一个目录分开。例如,home目录位于/目录下,因此它被称为/home/。类似地,如果我们有另一个位于/home目录上方的目录alice,它被表示为/home/alice/。

每个目录都用于组织特定类型和目的的文件。任何目录都可以包含四种类型的内容,如下表所示:

内容类型 描述
静态 这种类型的内容保持不变,直到明确编辑
动态或可变 这种类型的内容通常会不断修改
持久性 这种类型的内容在重启后仍然保留所做的更改,例如配置文件
运行时 这种类型的内容大多驻留在内存中,其内容会在重启时被清除,例如系统进程使用的文件

以下表格列出了 CentOS 7 中重要目录的位置和用途:

位置 用途
/boot 包含启动 CentOS 7 的引导过程所需的文件,包括 GRUB 配置文件、内核镜像(vmlinuz)、RAM 磁盘文件(initramfs)等。
/dev 包含系统用于访问硬件和软件设备的特殊设备文件,例如/dev/sda(硬盘驱动器)或/dev/pts1(表示伪终端)。
/etc 包含此系统上安装的应用程序的配置文件(如resolv.conf、passwd等),用于进行系统范围的更改。
/root 根用户的家目录,也称为超级用户的家目录。
/home 包含普通用户的家目录,用于存储个人文件。

| /run | 包含自上次启动以来为进程启动而产生的运行时数据、变量、进程 ID、锁文件等。该目录的内容会在重启系统后重新生成(在 CentOS 6 中,其内容存储在/var/run和/var/lock中)。该目录中的一个重要子目录如下:

  • /run/media: 用作可移动设备的挂载点,例如 USB、CD、DVD 等。

|

/var 包含特定于系统的可变数据,这些数据在重启后仍会保持。随着系统运行,这些文件的内容和大小会动态变化(例如日志文件、打印机缓存的文档、网站内容和 FTP 内容)。/var目录可以单独放在文件系统中,这样文件的增长就不会对系统造成致命影响。
/tmp 包含临时文件;为系统上的所有用户启用了写入权限。过去 10 天内未被访问、修改或更改的文件会自动从此目录中删除。我们系统中的另一个临时存储目录是/var/tmp。

| /usr | 包含应用程序文件、共享库和文档。该目录中的文件是静态的、只读的,并且是可共享的。它还包含三个重要的子目录,如下所示: |

  • /usr/bin: 包含基本的用户命令(ps、ls、cp等)

  • /usr/sbin: 包含系统管理命令(fsck、shutdown等)

  • /usr/local: 包含特定于本地计算机的数据和程序

  • /usr/include: 包含用于编译应用程序的头文件

|

/bin 指向/usr/bin的符号链接。
/sbin 指向/usr/sbin的符号链接。
/lib 指向/usr/lib的符号链接;包含应用程序使用的共享库,这些应用程序存储在bin和/sbin目录下。
/lib64 指向/usr/lib64的符号链接,包含应用程序使用的 64 位共享库,这些应用程序存储在/bin和/sbin目录下。
/mnt 该目录用于作为文件系统树中分区和设备的临时挂载点,例如用于挂载 NFS 文件系统。
/proc 包含虚拟文件系统(即它仅存在于内存中);也称为内核的伪文件系统。它包含动态的运行时系统信息(例如系统内存、已挂载设备、硬件配置等),被认为是内核的控制和信息中心。一些工具直接调用此目录中存储的文件并显示信息,例如通过/proc/meminfo文件查看空闲内存,使用/proc/net/arp文件查看 ARP 表信息,等等。

若要查看 Linux 文件系统层次结构标准的详细信息,可以参考使用 man 命令部分,并访问www.tldp.org/LDP/Linux-Filesystem-Hierarchy/html/获取在线参考资料。

使用 man 页面和 help 命令

我们可以花费大量时间学习 CentOS 7;这就像是给你端上做好的菜,但实际上我们可以学会如何烹饪,这样你就能自己做出不同的菜谱。Linux 有着最全面、最庞大的操作系统文档库,涵盖了大多数命令及其选项。无论你是经验丰富的用户还是初学者,你都无法记住所有 Linux 命令和工具的确切用法,每个命令都有多个选项。在这种情况下,Linux 文档将为我们提供帮助。

Linux 中可用的不同类型文档

在 Linux 中,有多种文档来源可供学习如何使用不同的命令及其选项,如下图所示:

Linux 中的不同类型文档

使用 man 命令

Man(手册页,manual的缩写)是 Linux 中最常用的文档来源,涵盖了系统内各种程序、工具、系统调用、库文件、配置文件和内核。整个 man 文档被组织成九个部分,每个部分针对特定类型的文档。如果某个命令有多个部分,默认情况下,它会显示遇到的第一个部分的文档。man命令的使用语法如下:

$ man <topic name>

执行上述命令后,指定主题的内容将逐屏显示。使用箭头键逐行滚动,或者按空格键切换到下一个屏幕。默认情况下,man 页面会在 less 查看器中打开。

下表列出了 man 页面导航命令键及其描述:

键 描述
空格键/Page Down 向下滚动一屏
Page Up 向上滚动一屏
下箭头 (↓) 向下滚动一行
上箭头 (↑) 向上滚动一行
/string 向前(下)搜索给定字符串在 man 页面中的位置
?string 向后(上)搜索给定字符串在手册页中的位置
n 在手册页中向前重复上一次的搜索
N 在手册页中向后重复上一次的搜索
q 退出手册并返回到提示符
g/Home 返回手册页的开始
G/End 跳转到手册页的末尾

一些常用的man命令选项包括以下内容:

  • $ man -f <topic name>:给出该主题的简短描述(相当于whatis命令)。使用方法请参见以下截图:

  • $ man -k <topic name>:列出所有包含指定主题的匹配页面(相当于apropos命令)。使用方法请参见以下截图:

  • $ man -a <topic name>:依次显示所有章节中包含指定主题名称的手册页。例如,man -a passwd会列出所有包含passwd的手册页,不论其属于哪个章节。

  • $ man <section number> <topic name>:强制man命令从指定的章节显示主题文档。否则,默认情况下,当没有指定章节号时,它会显示最常用的章节,如以下命令所示:

$ man passwd

执行上述命令后的输出如下所示:

指定章节的man命令会列出该章节的文档,如以下命令所示:

$ man 5 passwd

执行上述命令后的输出如下所示:

使用 GNU info 命令

Linux 中的下一个文档来源是 GNU 信息页面,其中的主题通过超链接连接。可以通过命令行使用info或pinfo命令,或借助图形工具来阅读信息页面中的文档。一些命令和工具同时拥有 info 和 man 文档,但 info 文档通常会更为详细。

在 info 页面中查看的主题被称为节点。每个节点可以包含菜单和子主题,称为项。项的名称前缀是星号(*)符号。你可以使用常规按键(箭头键、Page Up和Page Down)浏览主题列表。下表列出了在 info 页面中导航时最常用的按键:

Key Description
Page Down 或 空格键 向前滚动一页
Page Up 或 b 向上滚动一页
n 跳转到下一个节点
p 返回到上一个节点
u 在索引中向上移动一个节点
Tab 移动到下一个超链接(节点)
Enter 选择节点并显示当前光标位置的内容
q 退出查看 info 页面
/string 在打开的文档中搜索字符串
/<Enter Key> 向前重复上一次的搜索

在终端中键入info命令而不带任何参数,会显示可用主题的索引,如以下命令所示:

$ info <topic name>

执行前述命令时,输出结果如下截图所示:

使用 help 命令和--help 选项

help命令是 Linux 中另一个重要的文档来源。大多数 Linux 命令都有简短的描述,可以使用--help或-h选项以及命令或应用程序名称查看。

例如,你可以通过运行带有--help选项的mkdir命令来了解更多信息,如以下命令所示:

$ mkdir --help

执行前述命令时,输出结果如下截图所示:

--help选项作为快速参考非常方便,因为它显示了与给定命令相关的各种选项的有限信息。单独执行help命令会显示 Bash 中内置命令的列表。你也可以通过输入help后跟内置命令名来显示这些内置命令的帮助信息,如以下命令所示:

$ help exit

执行前述命令时,输出结果如下截图所示:

其他文档来源

除了man和pinfo之外,页面开发者还可以将文档包含在应用程序的 RPM 包中。这些文档会在安装包时安装,并且通常存储在/usr/share/doc/<packagename>目录中。它包含开发者希望共享的任何其他相关信息,但这些信息在该包的 man 页面中并未提供。你可能会在这些目录中找到基于 PDF、HTML 或 TXT 格式的文档、许可证协议、示例配置文件等等。

除了前述的文档来源,如果你安装了 GUI,那么gnome-help或Khelpcenter是系统上可用的其他文档来源。CentOS 7 的在线社区也包含大量的文档和帮助资源。每个 Linux 发行版都有自己用户驱动的论坛和 Wiki 部分。

CentOS 文档可在www.centos.org/docs/找到,但它正与 RHEL 文档合并,合并地点为access.redhat.com,因为相比之下 CentOS 的资源有限。

一些有用的命令可以提供其他命令的描述,以下是一些示例:

  • Whatis:此命令显示 Linux 系统中可用二进制文件的简短描述。在 CentOS 7 中,使用另一个命令makewhatis,该数据库会每天更新。

  • Whereis:此命令定位给定命令的二进制文件、源代码及手册页。

  • Which:此命令接受一个或多个命令名作为参数,并返回给定命令名的绝对路径。

管理带有路径扩展的文件名

在本节中,我们将看到可以提高文件管理效率的元字符和扩展技巧。

文件通配符匹配

bash shell 可以根据一些元字符来匹配路径名。这个功能被称为文件通配符匹配。路径名匹配能力在历史上被称为通配符匹配(也称为模式匹配),用于管理大量文件。它扩展了用于文件名和路径名的元字符。

使用文件通配符匹配文件名或路径名时,元字符在命令执行之前会被匹配的路径名列表所替代。以下表格列出了模式及其对应的结果:

模式 结果
? 匹配任何单个字符
* 匹配任何字符字符串(0 个或多个)
[set] 匹配集合中的任何字符;例如,[akl] 将匹配字符 a、k 或 l 的任意单个出现
[!set] 或 [^set] 匹配在字符集之外的任何字符
~ 匹配当前用户的主目录(称为波浪线展开)
~username 匹配用户名的主目录

通配符扩展

要使用 ? 通配符搜索文件,请用 ? 替换每个未知字符,如此例所示:

  • $ ls /etc/???.conf 将列出所有仅由三个字符组成的 conf 文件

要使用 * 通配符搜索文件,请用 * 替换未知字符串,如此例所示:

  • $ ls /etc/*.conf 将列出 /etc/ 目录中的所有 conf 文件

前面命令的结果如下所示:

波浪线展开

波浪线字符 ~,如果后面紧跟着一个斜杠 /,则匹配当前用户的主目录,如下图所示:

波浪线字符 ~,如果后面紧跟着一个字符串和一个斜杠 /,则匹配字符串中指定的用户名,如下图所示:

花括号扩展

花括号扩展生成一组字符字符串。在花括号内,我们指定一个由逗号分隔的字符串列表或一个序列表达式,它前后可以有文本来附加在花括号内的字符串上,如下图所示:

命令替换

命令替换允许将命令的输出存储到变量中;命令可以被自身替代。命令替换有两种方法:

  • 将命令包含在反引号内,如 `command`。使用反引号是一种较旧的方法,并且有两个缺点:

    • 反引号有时会与单引号混淆。

    • 反引号不能嵌套在其他反引号内,因此不支持嵌套命令替换。

  • 使用美元符号和括号将命令括起来,如$(command)。这种方式克服了在命令替换中使用反引号的缺点,如下图所示:

引用与转义

在 bash shell 中有一些特殊意义的字符,它们被称为元字符。Bash 元字符增强了 bash 的灵活性、功能和使用性。元字符的例子包括星号(*)、问号(?)、连字符(-)、感叹号(!)等。扩展元字符感叹号(!)的使用可以在第一章中找到解释,《CentOS 7 入门》一书的历史命令部分对其进行了详细讲解。引用和转义用于 bash shell 内部,以保护元字符扩展:

  • 转义:反斜杠(\)是一个转义字符,用于保护紧随其后的字符的特殊含义

  • 引用:为了保护较长的字符字符串,可以将其用单引号(')或双引号(")括起来

  • 双引号("):使用双引号可以抑制通配符和 shell 扩展,但允许命令和变量替换,如下图所示:

  • 单引号('):使用单引号可以抑制所有类型的扩展,单引号内的所有内容都被视为字面字符,没有任何特殊意义,如下图所示:

文件命名规范

文件或文件夹名称是用于标识文件的字符串。它可以由 255 个字符组成,包括字母、数字和特殊字符,但不能包含(/),因为它作为目录分隔符使用。你可以包含特殊字符(元字符);然而,不建议在文件名中使用某些字符,包括'、"、$、#、!等,因为这些字符在 shell 中有特殊含义。

Linux 是区分大小写的,空格也有特殊意义,因此文件名也是区分大小写的。这意味着,如果我们在同一目录下创建文件data.txt和Data.txt,它们将被视为两个独立的文件。

空格是 Linux 文件名中可以接受的字符;然而,空格也作为命令 shell 的分隔符,用于命令行语法解析,因此通常不建议在文件名中使用空格,以免在执行命令时造成歧义。

使用命令行工具管理文件

命令是安装在系统上的程序的名称。在进行基本命令操作之前,让我们先看一下 Linux 中的两种路径遍历方式:

  • 绝对路径:这种方法指定文件的完整路径,不论你当前的位置。这种路径总是以/(根目录)开头,并指定每个子目录的遍历顺序,以唯一表示文件系统中的某个文件。这样可以消除路径中的任何歧义。路径中的一个目录与另一个目录通过正斜杠(/)分隔。在创建 Shell 脚本时,应该使用这种命名约定来引用文件。与相对路径相比,绝对路径较长,但在命令行中频繁使用相对路径来引用文件或目录。

  • 相对路径:这种方法指定了相对于当前位置的文件路径。路径可以以一个或多个点符号(.)开头,也可以不以点符号开头。该路径永远不会以/开头。在这种遍历方法中,两个不同的工作位置可能在同一个 Linux 文件系统中具有相同的相对路径。使用 Shell 脚本时,应该避免使用这种命名约定,以确保脚本可以从 Linux 文件系统中的不同位置执行。

例如,如果你在/home/student的家目录下工作,并且想要移动到/home/student/backup目录,可以使用以下两种方法:

  • 绝对路径遍历:$ cd /home/student/backup

  • 相对路径遍历:$ cd backup:

backup目录的相对路径,当用户的当前工作目录是/home/student时,就是简单的backup。在这里,我们只使用cd命令指定目录名称,因为我们已经在/home/student目录下工作。

在标准的 Linux 文件系统中,文件的路径名(包括所有字符,甚至/目录分隔符)不能超过 4,095 字节。通常,使用相对路径进行导航比较容易,因为它需要更少的输入,并且可以利用元字符提供的快捷方式:

  • .:单点表示当前目录

  • ..:双点表示父目录

  • ~:波浪符表示用户的家目录

例如,假设你在/home/student的家目录下工作,想要移动到/usr/bin目录,可以使用以下两种方法:

  • 绝对路径遍历:# cd /usr/bin

  • 相对路径遍历:# cd ../../usr/bin

导航命令

这些命令属于导航类命令,主要用于路径导航:

  • pwd:pwd命令显示当前工作目录的完整路径。它有助于确定当前语法,以便与其他命令(如cp、mv、rm、mkdir等)一起使用相对路径,如下图所示:

  • ls: ls 命令用于列出给定目录的内容。如果未指定目录名,则列出当前目录的内容,如下图所示:

ls 命令有很多选项,通常一起使用以生成更结构化且易于阅读的输出。最常用的 ls 选项列在下面的表格中:

选项 描述
-a 显示以 (.) 开头的文件名,任何以 (.) 开头的文件默认是隐藏的
-l 显示详细信息,也叫长列表格式
-t 按修改时间排序列出内容,最近修改的文件排在最前
-r 按文件名反向排序列出内容
-h 以人类可读的格式显示文件大小(例如 1 K、50 M、3 G 等)
-S 按文件大小排序内容
-i 显示列出文件的 inode 号
-Z 显示每个文件的安全上下文(SELinux 参数)

ls 命令的使用示例如下图所示:

  • cd: cd 命令用于更改工作目录。我们通常使用相对路径名来简化命令行中的目录切换。然而,在创建脚本时,使用绝对路径名是一种良好的实践。cd 命令有很多选项,其中一些选项在下表中描述:
选项 描述
cd - 切换到上一个工作目录
cd 或 cd ~ 切换到用户的主目录
cd ~<username> 切换到指定 <username> 用户的主目录
cd . . 切换到上一级目录,即父目录

cd 命令使用示例如下图所示:

(. .) 表示当前工作目录的父目录,而 (.) 表示当前目录的相对路径格式。

文件管理命令

文件管理是创建、删除、复制和移动文件或目录的过程,用于逻辑地组织文件。在命令行上执行文件管理任务时,了解当前工作目录非常重要。这将帮助你为当前任务提供正确的绝对路径或相对路径。

cp 用于将文件或目录从一个位置复制到另一个位置。与此命令一起使用的各种有用选项列在下面的表格中:

命令 描述
cp file1 file2 将 file1 复制为 file2,并放置在当前目录
cp file1 file2 /tmp/ 将 file1 和 file2 复制到 /tmp/ 目录,并保留相同的文件名
cp file1 /tmp/myfile 将 file1 复制到 /tmp/ 目录,并重命名为 myfile
cp -r backup /tmp/ 将 backup 目录递归地复制到 /tmp/ 目录

以下是 cp 命令使用示例的截图:

mv 用于两个目的。首先,如果源路径和目标路径在同一目录下,它会重命名文件或目录。其次,当源目录和目标目录不同时,它用于执行剪切粘贴(移动)操作。

以下是 mv 命令中最常用的一些选项:

命令 描述
mv file1 file2 将当前目录下的 file1 重命名为 file2
mv file1 file2 /tmp/ 将 file1 和 file2 移动到 /tmp/ 目录下
mv file1 /tmp/myfile 将 file1 移动到 /tmp/ 目录,并重命名为 myfile
mv backup /tmp/ 将名为 backup 的目录移动到 /tmp/ 目录

以下是 mv 命令使用示例的截图:

mkdir 用于创建目录。此命令在命令行中也可与不同的选项一起使用,包括以下选项:

命令 描述
mkdir backup 在当前目录下创建一个名为 backup 的示例目录
mkdir /tmp/backup 在 /tmp 目录下创建一个名为 backup 的示例目录
mkdir -p backup/linux/centos 创建全路径的目录 backup/linux/centos(如果目标路径中缺少父目录,将自动创建完整路径)
mkdir linux windows mac 在当前目录下创建名为 linux、windows 和 mac 的目录

以下是 mkdir 命令使用示例的截图:

rmdir 用于仅删除空目录。如果目录中包含子目录或文件,则必须使用 rm -rf 命令,如下所示:

$ rmdir <empty directoryname>

以下是 rmdir 命令使用示例的截图:

rm 用于从文件系统中删除/移除一个文件。此命令也有多个选项,使用时需要小心,因为一旦文件被删除,它将无法从命令行模式下的回收站(Linux 的回收站)恢复。

这是一个列出了常用的 rm 命令选项及其描述的表格:

命令 描述
rm 删除一个文件
rm -f 强制删除文件
rm -i 交互式删除文件,在每次删除前进行提示(如果你不确定文件名,使用此选项)
rm -rf 强制递归删除目录(使用此选项时需谨慎)

以下是 rm 命令使用示例的截图:

ln命令用于创建链接。在 Linux 中有两种类型的链接,硬链接和软链接,也称为符号链接(symlink)。文件和目录的软链接可以看作是 Windows 中快捷方式的等价物,分别对应文件和文件夹:

  • 创建硬链接:$ ln file1 file2

  • 创建软链接:$ ln -s file1 file2

ln命令使用示例如下图所示:

管理归档文件和压缩文件

归档是将来自同一位置或不同位置的多个文件提取并打包成一个文件的过程。通常,这一过程会与压缩一同进行,或者紧接着进行压缩。这有助于简化备份过程,如下文所述。

压缩

文件数据通常会被压缩,以节省磁盘空间、减少流量,并减少通过网络传输文件所需的时间。Linux 有多种压缩工具,以下表格列出了其中的一些:

命令 描述
gzip 最流行的 Linux 压缩工具
gunzip 解压gzip压缩文件的工具
bzip2 另一种压缩工具,压缩效果优于gzip
bunzip2 用于解压.bzip2压缩文件的工具
xz Linux 中最节省空间的压缩工具
zip 流行的解压缩工具,用于解压其他操作系统的归档文件

这些工具有不同的压缩算法,因此具有不同的效率和资源消耗水平(一般来说,更高效的技术会消耗更多时间)。不同方法的解压时间差异不大。

gzip 和 gunzip 压缩

gzip工具比其他工具压缩文件的速度更快。

下表列出了gzip压缩命令及其描述,并附带一些示例:

命令 描述
gzip * 压缩当前目录中的所有文件,并将每个压缩文件重命名为.gz扩展名
gzip -r backup/ 压缩backup/目录及其子目录中的所有文件
gunzip myfile.gz 或 gzip -d myfile.gz 解压myfile.gz为myfile

gzip和gunzip命令的示例如下图所示:

bzip2 和 bunzip2 压缩

bzip2命令的语法与gzip类似,但它使用不同的压缩算法,并生成更小的压缩文件,但压缩所需的时间也更长。

下表列出了bzip2压缩命令及其描述,并附带一些示例:

命令 描述
bzip2 * 压缩当前目录中的所有文件,并将每个压缩文件重命名为.bz2扩展名
bunzip2 *.bz2 或 bzip2 -d *.bz2 解压当前目录下所有.bz2扩展名的文件

bzip2和bunzip2命令的示例如下所示:

xz 压缩

这是 Linux 中最节省空间的压缩工具。压缩的权衡是较慢的压缩速度,换来更高的压缩比。

下表列出了xz压缩命令及其描述,并附带了一些示例:

命令 描述
xz * 压缩当前目录下的所有文件,每个压缩文件都会被重命名为.xz扩展名
xz myfile 将myfile文件压缩为myfile.xz,默认压缩级别为 6;压缩后删除原始的myfile
xz -dk 解压myfile.xz到myfile并保留myfile.xz
xz -d *.xz 或 unxz 解压当前工作目录中所有.xz扩展名的文件

xz命令使用示例如下所示:

zip

这个程序通常不用于压缩 Linux 中的文件,但在从 Windows 操作系统解压归档文件时经常需要使用。

下表列出了zip命令及其描述,并附带了一些示例:

命令 描述
zip backup * 压缩当前工作目录中的所有文件,并将它们放入backup.zip中
zip -r backup.zip /home/student/abc 将存储在/home/student/abc中的文件和目录归档到backup.zip文件
unzip backup.zip 解压当前目录下的backup.zip文件中的所有文件

zip和unzip命令的示例如下所示:

归档

除了压缩,tar(磁带归档)工具常用于将文件归档成一个名为tarball的归档文件,然后将整个归档文件进行压缩。将多个文件放在一起形成一个单独的文件包称为归档。

以下表格列出了tar命令的各种选项及其描述:

tar 命令选项 描述
c 创建一个新的归档文件
v 显示详细信息,用于查看正在添加和提取的文件
f 要操作的归档文件名
x 提取归档文件
t 列出归档文件的内容
z 使用.gzip压缩(.tar.gz)
j 使用.bzip2压缩(.tar.bz2),比.gzip更优
J 使用.xz压缩(.tar.xz),比.bzip2更优

tar命令本身可以使用.gzip、.bzip2或.xz压缩归档文件。

下表列出了tar命令与压缩工具一起使用的选项:

命令 描述
Tar cvf abc.tar file1 file2 file3 归档 file1、file2 和 file3 文件,并将它们放入一个名为 abc.tar 的文件中
Tar xvf abc.tar 提取当前目录中 abc.tar 归档中的所有文件
Tar tvf abc.tar 列出 abc.tar 归档中所有可用的文件
Tar cvzf abc.tar.gz * 创建一个 abc.tar.gz 归档文件,其中包含当前目录中的所有文件,并使用 .gzip 压缩
Tar cvjf abc.tar.bz2 * 创建一个 abc.tar.bz2 归档文件,其中包含当前目录中的所有文件,并使用 .bzip2 压缩
Tar cvJf abc.tar.xz * 创建一个 abc.tar.xz 归档文件,其中包含当前目录中的所有文件,并使用 .xz 压缩
Tar xvf abc.tar.gz abc.tar.bz2 abc.tar.xz 提取当前目录中 abc.tar.gz、abc.tar.bz2 和 abc.tar.xz 中的所有文件

使用 tar 进行归档

在下面的示例中,我们将介绍如何创建和提取归档文件:

使用 tar 进行归档和压缩(.gzip)

在下面的示例中,我们将介绍如何创建和提取 gunzip 压缩档案:

使用 tar 进行归档、压缩(.bzip2)和列出内容

在下面的示例中,我们将介绍如何创建和提取 .bzip2 压缩档案:

使用 tar 进行归档和压缩(.xz)

在下面的示例中,我们将介绍如何创建和提取 .xz 压缩档案:

总结

在本章中,我们了解了 Linux 文件系统层次标准以及不同类型的内置文档。随后,我们介绍了基本的命令行操作,包括文件系统导航和从命令行管理文件系统。最后,我们亲自实践了 Linux 中的不同压缩技术和归档方法。

在下一章中,我们将学习不同的文本文件管理方法。

第三章:管理文本文件

计算机系统主要用于编辑、操作或管理数据。在 Linux 系统中,这些数据通常以文本文件的形式存在。一般来说,Linux 中的一切都是文件,掌握处理文本文件的技巧非常重要。Linux 中所有重要信息都存储在文本格式的文件中。

在本章中,我们的目标是学习如何在命令行中处理文本文件,使用最流行的默认基于文本的编辑器 vi 以及其他文本文件操作工具。然后,我们将学习如何在文件和程序中执行输入/输出重定向,以进行进一步处理。

在本章中,我们将涵盖以下主题:

  • 创建文本文件的不同方法

  • 使用 vi 编辑器编辑文件

  • 使用文本文件操作工具

  • 将输出重定向到文件和程序

  • 使用 grep 进行文本匹配

  • 使用 locate 和 find 命令查找文件

创建文本文件的不同方法

文本文件可以使用任何存在于 Linux 中的文本编辑器查看和编辑。然而,在学习编辑部分之前,我们必须对创建纯文本文件的不同方法有一个基本了解。根据需求,可以使用不同的方法来创建文本文件。接下来将介绍一些最常用的方法。

使用 cat 命令创建一个文本文件

如果我们想立即向一个新空白文件添加一些文本,可以使用 cat 命令来创建一个文本文件。使用 cat 命令创建文件的语法如下:

$ cat > demo.txt

按下 Enter 后,我们将返回提示符,可以直接开始向文件中插入文本。当你完成文本输入后,按下 Ctrl + D 来标记文件结束并返回提示符,如下图所示:

如果你想使用 cat 命令从 bash 脚本中创建文件,我们必须使用一种称为 here document 的操作符。它可以是任何任意字符串,用来标记文件的开始,并在新的一行中重复出现时标记文件的结束,如下图所示:

使用 touch 命令创建一个空文本文件

touch 命令的原始目的是更新文件的时间戳为当前的日期和时间,而不对文件内容进行修改。 touch 命令也可以用来创建一个大小为 0 字节的空文件。我们不能使用 touch 命令在文件中输入文本,但我们可以通过一个命令创建多个新文件。它通常用于创建计划将来使用的文件。 touch 命令的语法如下:

$ touch <path_for_empty_file>

以下截图显示了 touch 命令的示例:

使用重定向符号(>)创建一个文本文件

我们也可以使用重定向符号(>)创建文本文件,该符号用于将命令的输出重定向到文件。如果单独使用重定向符号而不前缀任何命令,它将创建一个空文件,大小为 0 字节,并且如果文件已存在,则会删除文件内容,如以下命令行所示:

$ > demo.txt

如果我们在任何命令前加上重定向符号(>),它将创建一个新文件,其中包含重定向符号前命令的输出,如下图所示:

我们可以通过重定向符号一次创建一个文件。

使用echo或printf命令创建文本文件

有时我们需要创建一个短小的文件,而不需要调用完整的文本编辑器。在这种情况下,可以使用echo或printf命令与重定向操作符一起创建空文件或包含单行内容的文件。创建文件的方法可以在脚本中使用,使用echo和printf命令的截图如下:

使用 vi 编辑器创建一个文本文件

vi 编辑器是最流行的命令行编辑器,并且是大多数 Linux 发行版的默认编辑器。它有三种操作模式,稍后将在本章中讨论。要使用 vi 编辑器创建文件,请按以下步骤操作:

  1. vi <文件名> 并按Enter

  2. 按I键进入插入模式并添加文本

  3. 持续向文件中添加自定义文本,直到完成

  4. 按Esc键进入命令模式

  5. 输入:wq并按Enter保存并退出

下图显示了在 vi 编辑器中创建文件的过程:

除了这种方法,还可以使用其他方式创建文本文件,如使用nano、ed、joe、emacs或pico编辑器。你也可以尝试使用这些编辑器。

使用 vi 编辑器编辑文件

vi 编辑器是最常用的编辑器,用于从 Shell 提示符编辑或创建新文件。它有文本界面和图形界面两种形式,且具有扩展功能。此文本编辑器用于编写脚本、编辑系统配置文件或开发编程语言的源代码。vi 的发音为“vee-eye”。

vim(vi 改进版)版本的 vi 编辑器具有许多增强功能,使得使用 vi 编辑器更加便捷。它支持扩展功能,如为许多配置文件和编程语言提供语法高亮。我们在这一节中学习的关于 vi 编辑器的知识也适用于 vim 编辑器。

vi 编辑器有三种操作模式,具体如下:

  • 命令模式

  • 插入模式

  • 行模式

下图展示了 vi 编辑器的不同模式以及切换模式的键位:

在使用 vi 编辑器时,了解当前工作模式至关重要。许多命令和按键在不同模式下的行为不同。下表简要描述了不同模式及其特性:

模式 功能
命令模式
  • 默认情况下,vi编辑器启动时处于命令模式

  • 命令模式中的按键被解释为修改内容的命令

  • 在此模式下,您可以给出命令以执行剪切、删除、复制和粘贴操作,并使用按键在文件中导航

  • 在此模式下无法编辑或插入文本

|

插入模式
  • 按下I键从命令模式切换到插入模式(按I键进入插入模式是最常用的选项;但是,还有其他键也可以按下来从命令模式进入插入模式)

  • 插入模式用于修改或插入文件中的文本

  • 插入模式在屏幕底部显示为- - INSERT - -

  • 按下Esc键退出插入模式并返回命令模式

|

行模式
  • 按下:键仅从命令模式切换到行模式(不能直接从插入模式切换到行模式)

  • 行模式由 vi 编辑器最后一行的冒号键:开头指示,光标放在冒号之后

  • 我们可以使用从旧的行编辑器继承的行编辑命令,如将文件内容保存到磁盘、执行 shell 命令以及读取其他文件的内容等。

  • 需要按下Enter键以执行命令

  • 按下Esc键退出行模式并返回命令模式

|

当你不确定当前工作模式时,按两次Esc键,即可返回命令模式。

使用 vi 编辑器处理文件

要启动 vi 编辑器并编辑文件,请使用以下语法:

$ vi <filename>

如果文件以指定的文件名存在,则将打开该文件并在命令模式下显示其内容。如果文件不存在,则在首次保存到磁盘时,vi将创建该文件。默认情况下,vi使用无名临时缓冲区编辑文件,直到其内容保存到磁盘。现在,让我们详细了解vi在不同模式下的工作方式。

插入模式

此模式用于在文件中输入新文本或修改现有文本。有多种方法可以进入插入模式,如下表所述:

键 用法
a 在当前光标位置之后插入文本,直到按下Esc键
A 在行的末尾插入文本,直到按下Esc键
i 在当前光标位置之前插入文本,直到按下Esc键
I 在行的开头插入文本,直到按下Esc键
o 在当前光标位置后插入新的一行以输入文本,直到按下Esc键
O 在当前光标位置前插入新的一行以输入文本,直到按下Esc键
s 删除当前光标位置的字符并保持在插入模式,直到按下Esc键
S 删除当前光标位置的行并进入插入模式,直到按下Esc键
r 替换当前光标位置的字符
R 从当前光标位置开始替换文本,直到按下Esc键

行模式

此模式用于执行编辑命令。在此模式下,最常执行的操作包括将文件保存到磁盘、关闭文件以及在不保存文件到磁盘的情况下退出 vi 编辑器。行模式操作需要在键入命令后按下Enter键。以下表格描述了行模式下最常用的一些操作:

操作 用法
保存并退出操作
:q 仅当编辑的文件没有做任何修改时,退出 vi 编辑器
:q! 退出 vi 编辑器,不保存当前打开文件的修改
:wq 将文件内容写入/保存到磁盘并退出 vi 编辑器
:x 将文件内容写入/保存到磁盘并退出 vi 编辑器
ZZ 从命令模式写入/保存文件内容到磁盘并退出 vi 编辑器
写入/保存文件操作
:w 将文件内容写入/保存到磁盘
:w demo 将文件内容写入/保存到磁盘,文件名为demo
:w! demo2 强制覆盖文件,文件名为demo2
:f demo3 将当前文件重命名为demo3
:w >> demo4 将当前文件附加到文件名为demo4的文件
:5,10w demo5 将第 5 行至第 10 行写入文件名为demo5的文件
:5,10w >>demo6 将第 5 行至第 10 行附加到文件名为demo6的文件
:r demo7 在当前光标位置读取文件名为demo7的文件内容
:e demo8 打开文件名为demo8的另一个文件
:e# 在打开的 vi 窗口之间切换(注意:此命令仅在你已用:w将文件保存到磁盘后有效)
搜索文件内容
/<pattern> 在缓冲区中向前搜索指定文本模式的出现
? 在缓冲区中向后搜索指定文本模式的出现
n 以正向方向重复上一次的搜索命令
N 以相反方向重复搜索命令

我们可以在行模式中执行替换操作。默认情况下,替换操作只会在当前行进行;然而,我们可以在替换命令s前加上地址选项,以在多行中执行替换,如下表所示:

行模式命令 描述
在当前行进行替换
:s/file/book 将当前行中第一个出现的 file 替换为 book
:s/file/book/g 将当前行中所有的 file 替换为 book
在指定的地址范围(x,y)之间进行替换
:1,5s/cat/dog/ 在第 1 到第 5 行之间将第一个出现的 cat 替换为 dog
:1,5s/cat/dog/g 在第 1 到第 5 行之间将所有出现的 cat 替换为 dog
在当前文件(%)中进行替换
:%s/cat/dog/ 将文件中第一个出现的 cat 替换为 dog
:%s/cat/dog/g 将文件中所有的 cat 替换为 dog
:%s/cat/dog/gc 在每次替换前进行提示,并将文件中所有的 cat 替换为 dog

确定 vi 编辑器中行模式的行号

行模式具有确定当前行号或正在编辑文件的总行数的能力。

下表列出了用于确定行号的命令:

命令 描述
:.= 该命令返回当前行的行号,并显示在屏幕的最后一行
:= 该命令返回屏幕最后一行的总行数
Ctrl + g 该快捷键在屏幕的最后一行显示当前行号以及文件中的总行数(命令模式快捷键组合)

如何在行模式下执行外部命令

在 vi 编辑器中执行 shell 命令有时非常有用。下表列出了在行模式下执行 shell 命令的一些示例:

行模式命令 描述
:! <shell command> 执行一个 shell 命令(按Enter键返回 vi 编辑器)
:!wc % 在 vi 编辑器中执行wc命令(%表示当前正在编辑的文件)
:sh 暂时返回到 shell 提示符(输入Exit返回 vi 编辑器)
:r !<shell command> 将 shell 命令的输出读取到当前光标位置的文件中

命令模式

这是 vi 编辑器的默认模式。在此模式下,大多数文件内容的浏览和导航操作都在此进行。除了文件内容的导航,还可以在命令模式下执行剪切、删除、复制和粘贴操作。下表描述了命令模式中的常用导航操作:

键 用法
按字符移动
箭头键 用于将光标向上、下、左、右移动
j 或 <enter> 将光标向下一行移动
k 将光标向上一行移动
h 或 Backspace 将光标向左移动一个字符
l 或 空格键 将光标向右移动一个字符
按单词移动
w 将光标移动到下一个单词的开头
b 将光标移动到前一个单词
e 将光标移动到当前单词的末尾
按行移动
0 或 ^ 将光标移动到行的开头
` 键
--- ---
按字符移动
箭头键 用于将光标向上、下、左、右移动
j 或 <enter> 将光标向下一行移动
k 将光标向上一行移动
h 或 Backspace 将光标向左移动一个字符
l 或 空格键 将光标向右移动一个字符
按单词移动
w 将光标移动到下一个单词的开头
b 将光标移动到前一个单词
e 将光标移动到当前单词的末尾
按行移动
0 或 ^ 将光标移动到行的开头
将光标移动到行尾
按句子移动
( 将光标移动到前一个句子的开头
) 将光标移动到下一个句子的末尾
按段落移动
{ 将光标移动到前一个段落的开头
} 将光标移动到下一个段落的末尾
按屏幕移动
Ctrl + F 或 Page Down 向前移动一个屏幕
Ctrl + B 或 Page Up 向后移动一个屏幕
Ctrl + D 向下移动半个屏幕
Ctrl + U 向上移动半个屏幕
H 屏幕上的第一行
M 屏幕中的中间行
L 屏幕上的最后一行
在整个文档中移动
:0 或 1G 或 gg 移动到文件的开头
:$ 或 G 移动到文件的最后一行
:n 或 nG 移动到第 n 行

| 接下来,我们将了解如何在命令模式下执行剪切、删除、复制和粘贴操作。删除字符会将文本放入一个未命名的临时缓冲区。删除的字符存储在临时缓冲区中,可以粘贴到其他位置。因此,我们可以说,删除和粘贴操作类似于剪切和粘贴操作。 |

| 在 vi 编辑器中,字符的复制被称为“复制”(yanking)。复制(yanking)操作使用y命令。以下表格描述了在 vi 编辑器中进行的各种剪切、复制、删除和粘贴操作: |

键 用法
删除/剪切单个字符
x 删除当前光标位置的一个字符
Nx 删除当前光标位置右侧的 N-1 个字符
3x 从当前光标位置开始删除共三个字符,依次是当前字符和右侧两个字符
X 删除光标左侧的一个字符
删除/剪切更大块的内容
dw 删除当前位置的单词,直到下一个空格或标点符号
db 删除一个单词(向后删除)
`d 键
--- ---
删除/剪切单个字符
x 删除当前光标位置的一个字符
Nx 删除当前光标位置右侧的 N-1 个字符
3x 从当前光标位置开始删除共三个字符,依次是当前字符和右侧两个字符
X 删除光标左侧的一个字符
删除/剪切更大块的内容
dw 删除当前位置的单词,直到下一个空格或标点符号
db 删除一个单词(向后删除)
删除从当前光标位置到行尾的内容
d^ 或 d0 删除从当前光标位置到行首的内容
dG 删除从当前行到文件末尾的内容
dgg 删除从当前行到文件的开头
D 删除当前行剩余的内容
dd 删除当前行
Ndd 或 dNd 从当前行删除 N 行
复制/复制文本(将文本放入临时缓冲区)
yw 复制一个单词
yb 复制一个单词(向后复制)
y$ 复制从当前光标位置到行尾的内容
y^ 或 y0 从当前光标位置到行首复制(yank)当前行
yy 复制当前行并将其放入缓冲区
Nyy 或 yNy 复制 N 行并将其放入缓冲区
p 粘贴当前行下方的内容(来自缓冲区的复制行)
P 粘贴当前行上方的内容
u 撤销上一个操作
Ctrl + R 重做上次的撤销操作

在提示符下输入 vimtutor 可以启动一个简洁但全面的初学者教程。该教程简短且切中要点,旨在使初学者熟练使用 vi 编辑器。

使用文本文件操作工具

系统管理员、开发人员和用户在使用 Linux 时需要处理文本文件、配置文件和日志文件。这些文件有的很大,有的较小或中等大小。这些文件中包含的数据通常需要查看、更新或提取。在本节中,我们将学习如何在 Linux 上管理和操作文本文件。

不同类型的编辑器用于查看文件内容

有不同类型的编辑器用于查看文件内容。一些编辑器,如 vim 或 nano,需要首先将整个文件加载到内存中。这些类型的编辑器不适合处理或查看大文件的内容,如银行数据库日志文件,因为打开这些大文件可能会由于高内存使用率而引发问题。然而,在这种情况下,您可以使用 less 命令来逐页查看大文件的内容,无需将整个文件一开始就加载到内存中。这比使用 vi 或 nano 等文本编辑器要快得多。

less 命令

这是用于查看较大文件的工具,因为它是一个分页程序;它按页显示内容,具有回滚功能。我们还可以执行搜索操作并在文件内部进行导航:

  • /<string>: 在正向方向搜索<string>

  • ?<string>: 在反向方向搜索<string>

  • q: 退出 less 编辑器

以下是 less 命令的示例:

$ less /var/log/messages or
$ cat /var/log/messages | less

主页页面使用 less 工具显示。

more 命令

该程序也用于查看较大的文件,因为它也是一个分页程序。它是一个较老的工具,选项较少。以下截图展示了 more 命令的示例:

cat 命令

连接(cat)是最常用的 Linux 命令行工具之一。它最常用来查看单个文件的内容或连接多个不太长的文件的内容。它不提供回滚功能。

以下截图展示了使用 cat 命令处理单个文件的示例:

以下截图演示了如何使用多个文件来利用cat命令:

我们可以使用cat命令执行多个任务,如下表所示:

命令 描述
cat file1 file2 连接file1和file2并显示输出。file1的完整内容后跟file2的内容
cat file1 file2 > file3 合并file1和file2的内容,并将输出保存到一个新的文件file3中
cat demo1 >> demo2 将demo1文件的内容附加到现有的demo2文件末尾
cat > demo 在终端中输入的任何后续行将进入demo文件,直到按下Ctrl + D
cat >> demo 输入的任何后续行将附加到demo文件中,直到按下Ctrl + D

tac 命令

tac 命令用于从下到上、从最后一行开始查看文件的内容。tac的语法与cat命令完全相同,如下截图所示:

head 命令

head 命令默认用于打印文件的前 10 行。然而,可以使用-n选项,或仅使用-<number>,来显示指定的不同数量的行。要显示内容的文件名作为参数传递给head命令,如下截图所示:

tail 命令

tail 命令默认用于打印文件的最后 10 行。然而,像head命令一样,我们可以使用-n选项或仅使用-<number>来更改显示的行数,如下截图所示:

tail 命令在我们使用日志文件排查问题时更为有用。它通过持续显示日志文件中新行的添加,帮助我们查看最新的输出行,从而让我们能够监控当前报告或记录的活动,如以下命令行所示:

$ tail -f /var/log/messages

wc 命令

wc 命令默认用于计算文件中的行数、单词数和字符数。它可以接受-l、-w或-c选项,分别仅显示行数、单词数或字符数。文件名作为参数传递给wc命令,如下截图所示:

file 命令

file 命令扫描文件头并告诉我们文件是什么类型。要识别的文件类型作为参数传递给file命令,如下截图所示:

查看压缩文件

在 Linux 中,我们可以在不解压的情况下查看压缩文件的内容。这是查看大型日志文件的一个好选择,这些文件使用该工具进行了压缩。有多个工具,其名称前缀带有字母z,用于处理.gzip压缩文件。

本表列出了一些z家族的命令:

命令 描述
zcat demo.gz 查看压缩的demo.gz文件
zless demo.gz或zmore demo.gz 按页查看压缩的demo.gz文件
zgrep -i host demo.gz 在压缩的demo.gz文件中搜索
zdiff file1.gz file2.gz 使用diff命令比较两个压缩文件,file1.gz和file2.gz
zcmp file1.gz file2.gz 使用cmp命令比较两个压缩文件,file1.gz和file2.gz

类似地,对于其他文本操作,可以将实用程序与其他压缩方法结合使用,例如bzip2和xz。要查看bzip2压缩档案中的文件内容,我们可以使用bzcat、bzless命令,而要查看xz压缩档案中的文件内容,我们可以分别使用xzcat和xzless。

zcat命令的使用方法在以下截图中展示:

zgrep命令的使用方法在以下截图中展示:

cut 命令

cut命令用于从文本文件或其他命令输出中仅显示特定的列或字符。例如,在以下命令中,我们从/etc/passwd文件中显示登录名:

$ cut -d: -f1 /etc/passwd

执行上述命令后的输出显示在以下截图中:

以下命令行显示了一个冒号分隔文件的第一和第三字段(输出去除了额外行):

$ cut -d: -f1,3 /etc/passwd 

执行上述命令后的输出显示在以下截图中:

以下命令行仅显示/etc/passwd文件中每行的前四个字符:

$ cut -c 1-4 /etc/passwd

sort 命令

sort命令用于按升序或降序排序文本文件的行,或按指定的键进行排序。以下示例演示了sort命令的工作原理。

以下截图展示了sort命令按升序排序/etc/passwd文件的示例:

以下截图展示了sort命令按第三字段数值排序/etc/passwd文件的示例。在这里,-t选项指定了分隔符,-k选项指定了用于排序的字段:

uniq 命令

uniq命令用于从已排序的文件中删除重复的行。它要求重复项位于相邻的行中,因此通常与sort命令结合使用,sort命令用于先对文件内容进行排序。uniq命令的语法如下:

$ sort <filename> | uniq
 or
$ sort -u <filename>

要计算文件中重复的行,请执行如下所示的命令行:

$ sort <filename> | uniq -c

要仅显示重复的条目,请执行如下所示的命令行:

$ sort <filename> | uniq -cd

paste 命令

paste命令用于合并来自不同文件的字段,或合并来自多个文件的行。例如,我们有两个文件,f1包含员工姓名,f2包含员工 ID 和电话号码。

要粘贴来自f1和f2的内容,请按命令行中的步骤执行,如下图所示:

要粘贴以分隔符分隔的内容,请执行paste命令,如下图所示:

常用的分隔符与-d选项一起使用,包括空格、Tab、|、:和逗号。paste命令的增强版本是join,它可以处理具有相似列的文件。

输出重定向到文件和程序

当我们执行任何程序时,默认情况下,它的输出或错误会显示在屏幕上。我们可以使用输入/输出重定向操作符将程序的文本输出重定向到文件,或者使用管道重定向到另一个程序。为此,当执行任何命令时,操作系统会创建并打开三个标准文件流(文件描述符)。这些流分别被称为标准输入(stdin)、标准输出(stdout)和标准错误(stderr)。

第一个流与stdin(编号为 0)关联,用于从键盘读取输入。第二个文件流与stdout(编号为 1)关联,用于程序在屏幕上打印输出,最后一个文件流是stderr(编号为 2),用于程序在屏幕上打印错误信息。

下表列出了不同的文件描述符(也称为通道),以及它们的数值、默认连接和符号名称:

通道描述 通道符号名称 默认连接 描述符值
标准输入 stdin 键盘 0
标准输出 stdout 终端 1
标准错误 stderr 终端 2
其他文件 filename 其他文件 3+

将stdout/stderr重定向到文件可以防止任何进程输出出现在终端上。Linux 有一个特殊的文件/dev/null,它丢弃重定向到它的任何通道输出。小于符号(<)用于从文件进行输入重定向,大于符号(>)用于将输出重定向到文件。如果我们将输出重定向符号(>>)重复使用两次而不是一次,它会将内容追加到文件名后缀。

下表解释了输入/输出重定向操作符的使用:

操作符使用 说明
Cmd > file 将命令输出重定向到一个文件
Cmd >> file 将命令输出重定向并附加到当前文件内容
Cmd 2> file 将命令的标准错误重定向到文件
Cmd 2>> file 将命令的标准错误附加到当前文件内容
Cmd 2> /dev/null 将标准错误消息重定向到/dev/null,丢弃错误消息
Cmd &> file 或 Cmd > file 2>&1 将标准输出和标准错误消息重定向到同一个文件
Cmd >> file 2>&1 将标准输出和标准错误消息附加到同一个文件中

以下是一些输出重定向的示例:

  • 通过执行以下命令将/var/log/messages的最后 10 行保存到f1中:

    $ tail -n 10 /var/log/message > f1
    
  • 通过执行以下命令,将date附加到名为f1的文件中:

    $ date >> f1
    
  • 将错误保存到名为error的文件中,并通过执行以下命令在屏幕上显示输出:

    $ find /etc/ -name passwd 2> error
    
  • 将输出保存到名为result的文件中,将错误保存到名为error的文件中:

    $ find /etc/ -name passwd > result 2> error
    
  • 将执行find命令时获得的输出或错误保存到名为both的常规文件中,如下命令所示:

    $ find /etc/ -name passwd &> both or
    $ find /etc/ -name passwd > both 2>&1
    
  • 将输出保存到名为result的文件中,丢弃错误消息,通过执行以下命令:

    $ find /etc/ -name passwd > result 2> /dev/null
    
  • 使用输入重定向从文件中读取数据,通过执行以下命令:

    $ wc -l < /etc/hosts
    

管道

Unix 哲学是将简单且简短的程序(命令)结合使用,以解决复杂的问题,而不是拥有一个复杂的程序,带有多个选项。为了实现这一目标,创建了管道,它将一个命令的输出作为输入传递给另一个命令。管道符号是两个或多个命令之间的竖线符号(|),如下所示:

$ command1 | command2 | command3 ..

以下是几个示例,展示了如何使用管道(将一个程序的输出重定向为另一个程序的输入):

  • 使用管道分页长输出,如下例所示:

    $ ls -l /bin | less
    
  • 将多个命令通过管道连接起来,如下例所示:

    $ ls | head -3 | tail -1
    
  • 如下例所示,结合管道和重定向:

    $ ls | head -3 | tail -1 > output
    
  • 将命令的标准输出以及标准错误通过管道传递给另一个进程,如下例所示:

    find /etc -name passwd |& wc -l or find /etc -name passwd 2>&1 | wc -l
    

tee 命令

使用管道的好处是,你不需要将命令的输出保存到临时文件中,再传递给其他命令进行处理。这样可以节省磁盘空间并提高执行速度,因为读写磁盘通常是系统中最慢的瓶颈。而且,如果你需要在传递给后续命令之前将输入保存到文件中,Linux 还有一个非常实用的命令,称为tee。tee命令的语法如下:

$ command1 | tee <log_filename> | command2 ......

以下是tee命令用法的示例:

  • 将ls命令的输出发送到wc命令并保存到名为listoffile的文件中:

    $ ls | tee listoffile | wc
    
  • 通过管道将标准输出以及命令的标准错误通过tee发送到另一个文件,并接着传递给后续命令:

    $ find /etc -name passwd |& tee logfile | wc -l
    

使用 grep 进行文本匹配

Grep(即Global Regular Expression Print的缩写)是一个广泛使用的命令,作为文本文件中的文本搜索工具。它搜索文件中的模式并打印包含匹配模式的相应行。它扫描文件以查找指定的模式,并且可以与正则表达式以及文本字符串一起使用。它的语法如下:

$ grep [options] pattern [files]

以下表格展示了使用grep命令时的情形:

命令 用法
grep 'student' /etc/passwd 在文件/etc/passwd中搜索字符串student,并打印所有匹配的行
grep -v 'student' /etc/passwd 打印所有不包含字符串student的行
grep -i 'STUDENT' /etc/passwd 以不区分大小写的方式搜索字符串STUDENT,并打印所有匹配的行(-i表示忽略大小写)
grep -c 'student' /etc/passwd 打印包含文本student的行的总数,来自/etc/passwd文件
grep -rl 'student' /etc/ 递归搜索目录,并打印包含字符串student的文件名
grep -rL student /etc/ 递归搜索目录,并打印不包含字符串student的文件名
grep -n 'student' /etc/passwd 打印包含模式student的行及其行号
grep -A1 'student' /etc/passwd 在匹配项之后打印额外的一行
grep -B1 'student' /etc/passwd 在匹配项之前打印额外的一行
grep -C1 'student' /etc/passwd 在匹配项前后各打印一行
grep -a 'dir' /bin/mkdir 在/bin/mkdir二进制文件内搜索,并打印包含字符串dir的行
grep 'root' /etc/passwd 打印包含字符串root的行
grep '^root' /etc/passwd 打印以字符串root开头的行
grep 'bash /etc/passwd 打印以字符串bash结尾的行
grep '^ <filename> 打印文件中的空行
grep -v '^ <filename> 仅打印文件中非空的行
grep '[br]oot' /etc/passwd 打印包含以字符b或r开头并紧跟字符串oot的行,位于/etc/passwd文件中的任意位置
who &#124; grep 'student' 从stdin读取输入,打印包含字符串student的行

使用grep匹配文件中的字符串的示例如下图所示:

使用grep打印不包含指定字符串的行的示例如下图所示(部分输出已被省略):

grep 命令可以与 -c 选项一起使用,以计算指定模式的出现次数。以下示例展示了如何使用 grep 命令计算系统中 CPU 核心的数量:

$ grep -c name /proc/cpuinfo (count the number of cpu cores in 
system)

以下截图展示了如何使用 grep 命令计算 root 字符串在 /etc/passwd 文件中的出现次数:

以下截图展示了如何使用 grep 打印匹配行的行号:

以下截图展示了如何打印以指定字符串开头的行:

使用 sed 和 awk 进行文本提取

经常需要从文件中重复提取相同的文本。对于这种操作,当我们需要在同一位置编辑文件或从多个文件中提取相同文本时,可以使用 sed 和 awk。虽然有多种文本提取工具,但这些工具使用较少的系统资源,执行速度更快,且更简便。

sed

这是最古老且最流行的 Unix 文本处理工具之一。它是一个非交互式流编辑器,通常用于过滤文本、执行文本替换以及对文本文件进行非交互式编辑。调用 sed 命令有两种主要方式,如下所示:

  • sed -e command <filename>:在命令行指定编辑命令,操作指定的文件并在终端显示输出。这里,-e 命令选项允许我们在命令行中同时指定多个编辑命令。

  • sed -f scriptfile <filename>:指定包含 sed 命令的脚本文件来操作指定的文件并在终端显示输出。

现在,我们将讨论使用 sed 执行的最常见操作,例如替换。以下表格列出了替换操作的基本语法:

命令 用途
sed 's/original_string/new_string/s file 用新的字符串替换每行中原始字符串的第一次出现
sed 's/original_string/new_string/g' file 用新的字符串替换每行中原始字符串的所有出现
sed '1,3s/original_string/new_string/g' file 用新的字符串替换文件中第 1 行到第 3 行之间每行中原始字符串的所有出现
sed -i 's/original_string/new_string/g' file 用新的字符串替换文件中每行原始字符串的所有出现

使用 sed 工具与打印命令:

p 命令将打印匹配的行,-n 选项会抑制标准输出,以便只显示匹配的行,如下所示的示例所示:

$ sed -n '1,3' /etc/passwd
$ sed -n '/^root/' /etc/passwd

使用 sed 工具进行替换 命令:

s命令将匹配的字符串替换为新字符串。s选项可以与范围前缀一起使用,以限制替换到指定数量的行,如以下示例所示:

$ sed '/^student/s/bash/sh/' /etc/passwd

使用sed工具并配合删除命令:

在下面的示例中,sed d命令将删除ntp.conf中的空行和注释行,并创建一个带有备份扩展名ntp.conf.backup的ntp.conf备份文件,如以下命令行所示:

$ sed -i.backup '/^#/d;/^$/d' /etc/ntp.conf

使用-i选项时要小心,因为一旦对文件进行修改,这些更改将不可逆转。通常更好的方法是先不使用-i选项运行sed,然后将输出重定向到一个新文件中。

awk

awk命令用于从文件中提取数据并打印特定内容。它经常用于重构数据并构建报告。它的名字来源于其创建者的姓氏:Alfred Aho、Peter Weinberger 和 Brian Kernighan。它的主要特性包括以下几点:

  • 它是一种类似于 C 的解释型编程语言

  • 它用于文件中的数据操作,并用于从文件中检索和处理文本

  • 它将文件视为记录和字段

  • 它有算术和字符串操作符

  • 它具有变量、条件语句和循环

  • 它从文件或标准输入设备读取,并将输出发送到像终端这样的标准输出设备

它的一般调用语法如下:

$ awk   '/pattern/{command}'   <filename>

从文件中打印选定的列或行是通常使用awk执行的基本任务。

在下面的示例中,awk命令用于逐行打印文件的内容,直到文件结束:

$ awk '{ print $0}' /etc/passwd

在下面的示例中,awk命令用于打印包含用户名student的行的第一个字段(列)。这里使用了-F选项将字段分隔符设置为:。

$ awk -F:  '/student/{ print $1}' /etc/passwd

在下面的示例中,awk命令用于打印文件/etc/passwd中包含匹配模式的行的选定字段:

$ awk -F: '/student/{print "Username :", $1, "Shell :", $7}' /etc/passwd

查找文件(locate 和 find 命令)

如果我们能快速找到所需的文件,那一定会让我们成为更快乐的 Linux 用户。我们可以在需要时搜索 Linux 系统中的任何目录或多个目录。CentOS 7 有两个常用工具用于查找文件:

  • locate命令

  • find命令

定位

该工具通过一个预先创建的文件和目录数据库进行搜索。它匹配包含指定字符字符串的所有条目。有时它会返回一个非常长的匹配结果列表,可以使用grep命令进一步筛选,如以下命令行所示:

$ locate zip | grep bin
$ locate iproute2

locate命令使用另一个程序updatedb创建的数据库。大多数 Linux 系统每天通过调度程序自动运行此程序。然而,我们可以通过在终端中运行updatedb命令,随时更新locate命令数据库。

查找

find是 Linux 系统中最有用且最常用的工具。它从任何位置遍历文件系统目录树,以指定条件搜索文件。其一般语法如下:

$ find  [pathnames]   [conditions]

我们可以在/var目录中搜索文件,查找其名称中包含特定字符串的文件,命令行如下所示:

$ find /var -name "*.log"

当没有给定任何参数(路径)时,它只会在当前目录及其子目录中搜索文件。

我们可以使用find命令搜索/usr目录中名为gcc的文件或目录,如下所示的命令行:

$ find /usr -name gcc

我们可以通过指定文件类型来缩小搜索范围,例如使用d查找目录,使用f查找文件,如下所示的命令行:

$ find /usr -type f -name gcc
$ find /usr -type d -name gcc

搜索大于特定大小的文件:

  • 以下find命令用于列出/var目录中大小为0 KB 的文件:
$ find /var -type f -size 0
  • 以下find命令用于列出/var/log目录中大小超过2 MB 的文件:
$ find /var/log -type f -size +2M
  • 以下find命令用于查找名为 messages 的文件,并使用gzip工具通过xargs压缩它:
$ find /var/log -type f -name messages | xargs gzip
  • 查找所有.jpg图像并使用xargs和tar进行归档,如下所示的命令行:
$ find / -name *.jpg -type f -print | xargs tar -cvzf images.tar.gz

总结

在本章中,我们首先学习了创建文本文件的各种方法。接着,我们走过了不同的文本操作工具,这些工具对于执行日常操作非常有帮助。这些工具主要包括head、tail、wc、sort、less和more等。然后,我们学习了将输入输出重定向到文件和程序的各种技术。之后,我们快速浏览了文本过滤和提取工具,如grep、sed和awk。最后,我们了解了如何使用 find 和 locate 命令在 CentOS 7 中搜索文件。

在我们下一章中,我们将学习如何在 CentOS 7 中管理用户和组。

第四章:用户和组管理

Linux 是一个多用户操作系统,因此对用户管理有基本的了解是至关重要的。在本章中,您将学习如何添加、删除、修改和暂停用户账户,并授予它们执行基本任务的权限。您还将学习如何在 Linux 环境中应用密码策略。

本章将涵盖以下内容:

  • 理解 CentOS 7 中不同类型的用户和组

  • 以超级用户身份执行命令在 CentOS 7 中

  • 创建、修改和删除本地用户账户

  • 创建、修改和删除本地组账户

  • 管理用户密码和密码过期策略

理解 CentOS 7 中的用户和组

管理不同类型的用户和组是系统管理的主要任务之一。通过将不同类型的用户和组账户作为基于角色的访问控制配置到系统中。根据用户的权限,我们可以限制用户访问各种系统资源。

定义用户

我们系统中运行的每个进程都由一个用户启动,并归该用户所有。运行进程访问不同文件和目录的权限由与该进程关联的用户决定。同样,系统中的每个文件都归某个用户所有,访问系统中不同文件和目录的权限也受到用户权限的限制。默认情况下,创建新文件的用户即为该文件的所有者。

在 Linux 系统中,通常有三种类型的用户账户:

  • 根用户(管理员)

  • 系统用户(由各种服务使用)

  • 普通用户(执行日常操作的普通用户)

识别当前用户

由于 Linux 是一个多用户操作系统,我们可以有多个用户同时登录。下表列出了用于查找登录用户及与用户相关的其他信息的不同命令:

命令 描述
$ who 显示当前登录用户
$ w 显示当前登录用户的详细信息
$ whoami 显示当前用户
$ id 显示当前登录用户的信息(如用户 ID、主组、次组和 SELinux 上下文)
$ id <用户名> 显示传递给 id 命令的用户名的相关信息

以下截图展示了 id 命令、who 命令和 w 命令使用的示例:

要查看与文件关联的用户,请使用长列表(ls -l)命令,该命令在第三列显示用户关联信息,如以下命令行所示:

$ ls -l /tmp

要查看与进程关联的用户,请使用带有 u 选项的 ps 命令。大多数时候,ps 命令也会与 a 选项一起使用,以显示与终端相关的所有进程,如以下命令所示:

$ ps -au

所有 Linux 用户都会分配一个唯一的整数,称为 用户 ID (UID)。Linux 系统使用特定的 UID 数字和范围来执行特定任务。

以下表格列出了不同的 UID 范围及其描述:

UID 描述
UID 0 根用户总是分配 UID 为 0。
UID 1-999 UID 1-999 分配给系统用户账户。其中,UID 1-200 静态分配给系统进程,UID 201-999 保留给系统。UID 201-999 在 CentOS 7 中安装应用程序时会动态分配给该应用程序。
UID 1000+ 常规用户账户默认从 UID 1000 开始。

用户信息的映射,如 username、UID、GID 和用户的 home 目录,定义在一个纯文本文件 /etc/passwd 中。/etc/passwd 文件包含七个由冒号分隔的字段,如下所示:

username : password : UID : GID: Gecos : /home/dir : Default shell

以下表格描述了 /etc/passwd 文件的各个字段:

字段 描述
username 它是与 UID 关联的用户登录名,方便人类阅读(应为 1 到 32 个字符之间)。
password 在此字段中,密码最初以加密格式存储。现在,它们存储在 /etc/shadow 文件中。
UID 它是系统用来识别用户的 UID:UID 0:保留给 rootUID 1-200:保留给预定义的系统账户(静态)UID 201-999:保留给系统账户(动态)UID 1000+:保留给常规用户账户
GID 它是用户的主 GID,由系统用来将用户与其主组关联
Gecos 该字段是可选的,包含与用户相关的额外信息,如用户的全名、地址、联系方式等
/home/dir 该字段包含用户主目录的绝对路径
默认 shell 它是用户默认 shell 的绝对路径(该程序在用户登录系统时运行),提供用户的命令提示符

/etc/passwd 文件中最后两行的内容如下所示:

理解 Linux 中的组

Linux 使用组来组织系统中的用户。组是具有某些共享特征和访问控制的账户集合。像用户一样,组也有一个名称,该名称与一个称为 组 ID (GID) 的数字相关联,通常与 UID 相同。本地组信息存储在 /etc/group 文件中。与用户账户相关的组有两种类型:

  • 主组:

    • 每个用户只有一个主组。

    • 它是用户所属的默认组。

    • 每个本地用户的主组由 /etc/passwd 文件第三字段中列出的组的 GID 编号定义。

    • 默认情况下,主组拥有用户创建的所有新文件。

    • 通常,新创建用户的主组将与用户同名。每个用户是其私人主组的唯一成员。

  • 补充组:

    • 每个用户可以与 0 个或多个补充组相关联。

    • 每个本地用户的附加组条目在/etc/group文件的最后一个字段中定义。此文件包含一个以逗号分隔的用户列表,决定了用户所属组的组成员身份。

    • 补充组成员身份有助于实现对系统中文件和其他资源的访问权限、特权和安全考虑。/etc/group文件的各个字段如下:

groupname : password : GID : <comma separated list of users who belong to this group>

以下截图显示了/etc/group文件最后两行的内容:

在 CentOS 7 中以超级用户身份执行命令

每个操作系统都有一个账户来管理系统的资源。在 CentOS Linux 中,这个用户账户被称为root,通常称为超级用户。root 账户是 Linux/Unix 系统中权限最高的账户。此账户用于执行系统管理任务,如管理用户账户及其密码、管理软件包、修改系统文件和重启系统服务。以 root 用户身份工作时必须特别小心,因为它没有任何安全限制。如果 root 账户被破坏,另一个人将完全控制该系统。Linux 中的 root 账户相当于 Windows 中的本地管理员账户。

当以 root 用户身份登录时,shell 提示符会显示#符号,表示你正在作为系统中权限最高的用户工作。

在 Linux 中,有两个命令,su和sudo,用于暂时授予普通用户 root 访问权限。我们将逐一讨论这些命令。

使用su命令切换用户

su(即switch user或substitute user的缩写)命令用于切换到其他用户账户。如果su命令没有指定用户名作为参数,它会默认考虑 root 账户。该命令有两种调用方式,如下所示:

  • $ su - <用户名>:此方法启动一个新的登录 shell,并指定另一个用户名。它将设置 shell 环境,就像在系统中作为该用户进行正常登录一样。

  • $ su <用户名>:此方法启动一个非登录 shell,并指定用户名。它只会使用当前用户的环境设置启动新的 shell,而不会调用其他用户名的 shell 变量。

    如果没有指定任何用户名,su –将调用 root shell,并要求在提示符处输入 root 凭据,如以下截图所示:

使用su命令授予普通用户 root 访问权限的缺点

一旦用户通过su登录为 root 账户,他们可以在不再询问 root 密码的情况下,做任何事情,直到注销为止。该命令的日志功能也有限。

使用sudo以根用户身份运行命令

在前面的方法中,标准用户通过su命令临时成为 root;通过指定root密码授予 root 的所有权限。此方法不适用于以 root 身份运行某些程序,因为它给普通用户授予了无限的权限。使用sudo授予权限更安全,也是首选的方法。

sudo功能用于根据/etc/sudoers文件中的设置,分配更多有限的权限给用户账户。在这种方法中,sudo要求用户输入他们自己的密码进行身份验证,而不是他们试图访问的账户的密码。这种方法使他们能够委派系统管理任务,而不需要让他们接触 root 密码。我们还可以将用户的权限限制为一组特定的命令;也就是说,他们只能以 root 身份执行有限数量的指定命令。通过sudo执行的任何命令默认会被记录到/var/log/secure日志文件中。

要以 root 权限执行单个命令,输入sudo <command>。命令执行后,您将返回到普通的无权限用户。以下截图展示了使用sudo执行仅iptables命令的例子:

使用sudo执行的命令日志存储在/var/log/secure中,如下图所示:

下面的截图展示了通过在/etc/sudoers文件中进行必要的条目,来授予用户执行管理员命令的权限的示例:

在 CentOS 7 中,所有属于 wheel 组的成员都可以通过指定自己的密码,使用sudo以 root 身份运行任何命令。CentOS 7 中/etc/sudoers文件中并没有将其设置为默认规则。

创建、修改或删除本地用户账户

在 CentOS 7 中有多个命令可用于管理本地用户账户。本节仅介绍 CentOS 7 中用于管理本地用户账户的最常用命令。

使用useradd命令创建用户

useradd命令在没有选项的情况下运行时,会创建一个具有默认参数的用户账户。默认参数是从/etc/login.defs文件中读取的,包括有效的 UID、GID 号、默认的密码过期规则等。这些值仅在创建新用户时使用。useradd的语法如下:

$ useradd    <username>

useradd --help将显示可以与useradd命令一起使用的选项,以覆盖默认参数。

使用useradd命令创建用户帐户的示例,如下截图所示:

除了useradd,我们还可以使用adduser命令在 Linux 中创建本地用户帐户。您可以通过man adduser命令阅读有关adduser的更多信息。

使用usermod命令修改用户

usermod命令与各种选项一起使用,以修改现有的用户帐户参数。运行usermod --help命令将显示可以使用的各种选项。usermod的语法如下:

$ usermod    -<option>     <username>

以下表格列出了与usermod命令常用选项及其描述:

选项 描述
usermod -c "Comments" <username> 在 GECOS 字段中添加注释,例如用户的全名、地址、电话号码等。
usermod -g <gid> <username> 修改用户的主组。
usermod -G <groupname> <username> 修改用户的辅助组。
usermod -a -G <groupname> <user> 仅与-G选项一起使用。它将用户添加到指定的辅助组中,而不会将用户从其他组中移除。
usermod -s <shell> <username> 修改用户帐户的登录 shell。
usermod -L <username> 锁定用户帐户。
usermod -U <username> 解锁用户帐户。

使用usermod命令修改用户登录 shell 的示例,如下截图所示:

以下命令用于查看与用户相关联的groups:

$ groups <username>
$ groups sam

usermod命令可以用于在用户的现有辅助组中添加新的辅助组。以下命令将把新的辅助组 wheel 添加到用户sam的现有辅助组中,如下截图所示:

使用userdel命令删除用户帐户

userdel命令用于删除现有的用户帐户。userdel命令可以以两种方式使用,如下所述:

  • userdel <username>:这将从/etc/passwd文件中删除用户条目,但保留用户的主目录和邮件不变。这种删除用户帐户的方式不推荐使用。

  • userdel -r <username>:这将删除用户及其主目录以及用户的邮件箱。这样会从用户的主目录中删除由用户拥有的文件及其帐户。带有-r选项的userdel命令示例如下:

创建、修改或删除本地组帐户

组用于组织用户。一个组是具有共享权限的账户集合。然而,组必须在用户被添加到该组之前存在。CentOS 7 中有多个命令可以用于管理组账户。本节仅介绍在 CentOS 7 中管理本地组账户的最常用命令。

组成员控制由/etc/group文件管理。该文件列出了组及其成员。

使用groupadd创建附加组

groupadd 命令可以与多个选项一起使用,用于为用户账户创建附加组,或创建系统用户组。

下表列出了groupadd命令及其不同选项的描述:

命令 描述
groupadd <groupname> 从/etc/login.defs文件中给定的范围内的下一个可用 GID 创建用户私有组(GID 1000+)。
groupadd -g GID <groupname> 使用给定的 GID 创建用户私有组
groupadd -r <groupname> 使用默认系统组范围(1-999)中的 GID,或/etc/login.defs文件中给定的 GID 创建一个系统组。

以下截图展示了groupadd命令使用的示例:

使用groupmod命令修改现有组

groupmod 命令用于修改组属性,如组的 GID、组名等。下图中的示例展示了如何使用groupmod命令及-n选项来修改指定组的groupname:

-g选项用于为现有的groupname分配新的 GID,如下图所示:

使用groupdel命令删除组

groupdel 命令通常用于从系统中删除一个组,前提是该组不是任何现有用户的主组。以下命令行展示了如何使用groupdel命令从系统中删除名为appusers的组:

$ groupdel appusers
$ tail -2 /etc/group

管理用户密码和过期策略

本节介绍用于管理密码和密码过期参数的命令,这些命令适用于 CentOS 7 中的 shadow 密码文件。

使用passwd命令设置用户密码

passwd 命令用于设置用户的初始密码或修改用户现有密码。passwd命令的语法如下:

$ passwd    <username>

root 用户可以为任何用户设置密码,而无需知道其当前密码。对于普通用户,默认策略是使用至少八位字符的密码,并且密码不能是字典单词、用户名或以前的密码。以下截图展示了使用passwd命令更新用户密码的示例:

理解 shadow 密码文件

在 Linux 发展的早期,加密的密码存储在一个可读的文件中,/etc/passwd。在字典攻击对加密密码的攻击日益猖獗之前,这被认为是存储密码的安全机制。现在,为了加强 Linux 安全性,加密的密码(盐化密码哈希)存储在/etc/shadow文件中。此文件还包含密码老化策略参数。只有 root 权限的用户可以修改或读取此文件。我们可以通过执行以下命令查看此文件的最后一行: |

# tail -1 /etc/shadow

执行前述命令后,我们得到以下输出,其中显示了加密的密码、盐和各种密码老化参数: |

jack:$6$cKc/hj8V$JZPyiz6TMpz/YpPtSPdNARPd/gXxLqm3c0qHZinNmweXEpM/IMBYGiBYXZw7OuzLnr0YkFdZZifPvywkJYuqv0:17783:0:99999:7:::

在前述输出中,/etc/shadow文件的第二个字段是密码字段,包含以下三个信息,使用$符号分隔,存储在/etc/shadow文件中: |

  • 6: 它表示用于加密密码的哈希算法。数字 1 表示 MD5 哈希,数字 5 表示 SHA-256 哈希,数字 6 表示 SHA-512 哈希算法。 |

  • cKc/hj8V: 它表示用于加密哈希的随机盐值。这个盐值与未加密的密码结合后加密生成密码哈希。使用盐可以防止两个或更多使用相同密码的用户在/etc/shadow文件中拥有相同的条目。 |

  • JZPyiz6TMpz/YpPtSPdNARPd/gXxLqm3c0qHZinNmweXEpM/IMBYGiBYXZw7OuzLnr0YkFdZZifPvywkJYuqv0: 它是加密的哈希值。 |

当用户在登录提示符下输入密码时,系统会查找/etc/shadow中的用户条目,然后将用户的盐与未加密的密码结合,并使用指定的哈希算法生成哈希值。如果密码匹配,用户将成功登录;否则,登录尝试失败。 |

理解密码老化参数 |

chage命令用于列出现有的密码老化策略或修改该策略。/etc/shadow文件包含九个由冒号分隔的字段,其中包括加密的密码和密码老化策略。以下是/etc/shadow文件中包含信息的格式: |

name : password : lastchange : minage : maxage : warning : inactive : expire : blank

下表列出了/etc/shadow文件字段及其描述: |

字段 描述
登录名 它是本地系统中的用户帐户登录名。
密码 它是加密的密码。如果该字段包含!符号,则表示密码已被锁定。
最后更改 它是最后一次密码更改的日期,以自01.01.1970以来的天数表示。
最小年龄 它是密码在更改之前必须保持的最小天数。0表示没有最小天数要求。
最大年龄 它是密码必须更改的最大天数。
警告期 这是密码过期前的天数,当此时用户将开始接收到更改密码的警告。此字段中的0表示不会给出警告。
不活跃 这是密码过期后账户仍然保持活跃的天数。在这个不活跃期间,用户仍然可以登录并更改密码。超过指定天数后,账户将被锁定并变为不活跃状态。
过期日期 这是账户过期日期,表示自01.01.1970以来的天数。
空白 为将来使用预留的空白字段。

默认情况下,密码设置为不自动过期。强制密码过期是强大安全策略的一部分。我们可以通过修改/etc/login.defs文件来更改默认的过期设置。我们还可以使用chage命令来更改密码过期策略。chage命令的语法如下所示:

$ chage    [option]    <username>

下面的截图展示了使用chage命令列出用户所有现有密码过期策略参数的例子:

下表列出了与chage命令一起使用的各种选项及其描述:

选项 描述
Chage -l <username> 列出用户当前的所有密码过期参数设置
Chage -d 0 <username> 强制用户在下次登录时更改密码
Chage -m 3 <username> 设置用户可以保留密码的最短天数
Chage -M 30 <username> 设置用户可以保留密码的最长天数(-1表示无限期)
Chage -W 7 <username> 设置用户在密码更改前开始接收警告的天数
Chage -d YYY-MM-DD <username> 设置密码的最后更改日期(/etc/shadow文件记录自 1970 年 1 月 1 日起的天数)
Chage -E YYYY-MM-DD <username> 设置用户的密码过期日期(/etc/shadow文件记录自 1970 年 1 月 1 日起的天数)

下面的截图展示了使用chage命令修改各种参数的例子:

限制用户访问

一旦使用chage命令设置的账户过期日期到达,用户将无法与系统进行交互式登录。chage命令的一些参数可以通过useradd和usermod命令设置。可以使用usermod命令通过-L选项来锁定账户,如下所示:

# usermod -L jack
# su - jack

我们还可以使用-U选项来解锁用户账户,如下所示:

# usermod -U jack

假壳或 nologin shell

有时,我们可能需要一个带有密码的用户帐户来进行系统身份验证,但不需要为该用户名提供交互式 shell。这样有助于防止该用户帐户使用密码登录系统。在这种情况下,我们可以将用户的 shell 设置为/sbin/nologin。如果用户尝试登录系统,nologin shell 将关闭用户的连接,如下图所示:

这样的情况示例可能是邮件服务器,在这种情况下,需要一个用户帐户来存储邮件和密码,以便用户可以通过邮件客户端进行身份验证并接收邮件;然而,如果分配了/sbin/nologin shell,则该用户无法使用该帐户登录系统。

总结

本章开始时,我们学习了 CentOS 7 中不同类型的用户和组。接着,我们了解了 su 和 sudo 之间的区别,它们可以临时授予用户 root 权限。然后,我们学习了如何管理本地用户帐户和本地用户组。最后,我们查看了密码如何在 Linux 中设置和存储,以及 CentOS 7 中密码过期策略的实现方式。

在下一章,我们将学习如何在 CentOS 7 中管理文件权限。

第五章:管理文件权限

权限是 Linux 在正确应用时增强安全性的几个优点之一。由于 Linux 是一个多用户操作系统,不同的用户将同时处理多个程序和文件等。权限有助于保持安全和组织。在本章中,您将学习如何使用基本的读取、写入和执行权限以及用户或组所有权来管理文件的访问控制。您还将学习如何应用特殊权限和访问控制列表(ACL)。

在本章中,我们将讨论以下主题:

  • 理解 Linux 文件系统权限

  • 管理文件权限

  • 管理文件所有权

  • 特殊权限

  • 管理默认权限

  • 管理文件上的 ACL

理解 Linux 文件系统权限

在基于 Linux/Unix 的操作系统中,每个文件都属于一个用户和一个组。默认情况下,创建文件的用户是该文件的所有者,文件属于该用户的主组。通过 Linux 文件系统访问文件的权限由应用于该文件的权限控制。这些权限针对文件的所有者(也称为用户)、该文件的组(也称为组所有者)以及系统中的其他所有人(也称为其他人)进行分类。

有三种标准权限类型应用于文件:

  • 读取,由字母r表示

  • 写入,由字母w表示

  • 执行,由字母x表示

这些通常以三元组(如rwx或r-w)的形式分组,用于表示一类权限。每个文件有三类权限;也就是说,这些权限影响系统中的三个类别的访问:

  • 用户/所有者(u):描述适用于文件所有者的权限。默认情况下,创建文件的用户即为所有者。

  • 组(g):描述适用于拥有文件的组的权限。

  • 其他人/所有人(o):描述系统中其他所有人的权限。

权限对文件和目录的影响

权限控制对文件和目录的访问。相同的权限对文件和目录有不同的影响。

下面是列出权限及其对文件和目录的相应影响的表格:

权限 对文件的影响 对目录的影响
读取(r) 可以读取文件内容 可以使用ls命令列出目录内容
写入(w) 可以修改文件内容 我们可以创建或删除文件并修改文件或目录的权限
执行(x) 我们可以将文件作为命令执行 可以访问目录内容(我们可以在该目录上使用cd命令)

如果用户对某个目录具有读取权限,意味着他们可以仅通过ls命令列出目录中的文件名。如果用户仅对某个目录具有执行权限,则不能使用ls命令列出目录的内容;然而,如果用户知道该目录的内容,他们可以通过明确访问文件名来访问目录内容。

任何用户只要对文件所在目录具有写权限,就可以删除该文件或子目录,而与文件本身的所有权或权限无关。Root 用户拥有完全的权限控制;它可以访问或删除文件系统中的任何文件。然而,存在一些高级权限,如chattr和安全增强 Linux(SELinux)控制,这些可以用于为 Root 创建访问控制。SELinux 是一种强制访问控制,相关内容在第九章中讨论,概述和必要的高级实用工具。

查看应用的权限和所有权

使用ls命令加上-l选项可以获取目录内容的详细信息,包括权限和所有权。它将列出目录中所有文件的详细信息。为了防止进入子目录并查看目录本身的信息,可以在ls命令中使用-d选项,如下图所示:

长格式列出命令的第一个字符告诉我们文件的类型。这里的连字符(-)表示一个普通文件,它可以包含数据或文本,或者是一个二进制文件。下表列出了各种文件类型及其在长格式列表中作为第一个字符的标识符。

下面是列出文件类型及其描述的表格:

类型 描述
- 文件
d 目录
l 链接(符号链接,类似于 Windows 上的快捷方式)
c 字符设备文件
b 块设备文件
s 套接字类型文件
p 命名管道

管理文件权限

chmod命令用于修改文件的权限。更改模式(chmod)权限也称为文件的模式。使用chmod,我们可以分别修改系统中所有者、组和其他用户的权限。我们可以通过两种方式使用chmod来修改权限:一种是使用数字,另一种是使用符号表示法。

使用符号修改文件权限(chmod)

chmod命令用于更改文件或目录的权限或模式。它将新的权限集作为第一个参数,后跟文件和目录的列表,应用这些新权限。符号方法的语法如下:

$ chmod     whowhatwhich    file   |   directory

下面是列出与chmod一起使用的关键字及其描述的表格:

关键字 描述
谁 它表示您想要更改权限的人:u:用户权限g:组权限o:其他权限a:所有用户权限如果在此字段中未指定任何内容,则采用(a)作为默认值。
什么 它表示您想要对权限执行的操作:+:在现有权限集中添加一些权限-:从现有权限集中删除一些权限=:精确设置指定的权限,不考虑现有权限集
哪一个 它表示您正在使用哪些权限:r:读w:写x:执行

以下是一些示例,说明使用chmod命令的用法,使用符号:

列出名为myfile的文件的现有权限,如下屏幕截图所示:

为名为myfile的文件添加用户执行权限,如下屏幕截图所示:

从组中删除写权限,并为名为myfile的文件添加其他用户执行权限,如下屏幕截图所示:

精确设置读权限,并从所有名为myfile的文件中删除任何现有权限,如下屏幕截图所示:

精确设置并从名为myfile的文件中删除所有其他人的现有权限,如下屏幕截图所示:

使用数字管理chmod命令的文件权限

chmod命令也可用于修改文件或目录的权限,使用数字方法。此方法使用chmod命令精确设置指定的新权限,不考虑文件或目录的现有权限。在数字方法中,权限用三位八进制数(或设置特殊权限时为四位数)表示。每个八进制数表示一个访问级别(用户、组或其他)的权限总和,数字介于零到七之间。使用数字应用权限的语法如下所示:

$ chmod     ###     file   |    directory

这里,每个#表示用户、组和其他访问级别的权限,从左到右。它是该访问级别所有权限(读、写和执行)的总和,每个权限具有特定的数字权重,如下所示:

这是一个列出权限数字权重的表格:

权限 数字权重
读(r) 4
写(w) 2
执行(x) 1

使用数字方法设置权限时,我们计算我们需要为用户、组或其他人分配的所有权限的总和;例如,如果您希望为file1使用set-rwx-r-xr--作为新的权限,则执行以下操作:

user → rwx → 4+2+1=7

group → r-x → 4+1=5

others → r- - → 4=4

以下是chmod命令的示例,展示了如何使用数字设置权限以及使用符号设置相同权限的chmod用法:

$ chmod 754 file1 
$ chmod u=rwx,g=rx,o=r file1 

以下是一些示例,说明如何使用数字设置chmod命令的权限:

为名为file1的文件设置用户的读权限、组的写权限,并为其他用户设置无权限,如下截图所示:

使用带有-R选项的chmod命令可以递归地设置目录中所有文件和子目录的权限。使用X选项,你可以为目录(而非文件)添加或移除执行权限。虽然这个选项不常用,但在某些情况下很有用;你可以使用chmod -R +rX /data为/data文件夹中的目录设置执行权限,但不会影响其中的文件。

管理文件所有权

在 Linux 系统上创建的每个文件或目录都属于一个用户和一个组,这些都被称为文件的所有者或文件的组所有者。文件或目录的所有权可以由根用户或文件所有者修改。而组所有权只能由根用户或文件所有者修改,且只对该所有者所属的组有效。本节将介绍如何管理文件和目录的所有权。

理解默认的文件所有权

当我们创建文件或目录时,它会获得某些默认的所有权和组所有权。创建文件的用户成为该文件的用户(所有者),该用户的主组成为该文件的组。要确定用户或组是否有权限访问文件或目录,shell 会按以下顺序检查文件的所有权:

  1. 访问文件时,shell 会检查你是否是文件的所有者。如果用户是文件的所有者,那么该用户将根据为文件所有者设置的权限访问该文件。

  2. 如果用户不是文件的所有者,shell 会检查文件所属的组。如果用户是该组的成员,那么他将根据该组的权限访问文件。

  3. 如果用户既不是文件的所有者,也不属于文件所属的组,则该用户将根据其他权限访问该文件。

使用长列表命令ls -l可以查看文件当前的所有权。该命令输出的第三和第四列显示文件的所有者和所属组,如下图所示:

使用chown修改用户所有权

chown命令可用于更改文件或目录的用户所有权以及组所有权。首先,我们将看到如何使用chown命令更改文件所有权。chown命令的语法如下:

$ chown    <user_name_to_set_as_owner>    <file_or_foldername>

以下是一些示例,说明了 chown 命令的使用:

使用 ls 命令列出名为 myfile 的文件的当前所有权,如下所示:

$ ls -l myfile

将名为 myfile 的文件的用户所有权授予 jack,如下所示的截图所示:

chown 命令常常与 -R 选项一起使用,用于递归修改整个目录树的所有权。以下命令用于将名为 mydir 的目录及其中的所有文件和子目录的所有权授予用户 jack,如下所示的截图所示:

使用 chown 修改组所有权

chown 命令也可以通过在组名之前加上冒号(:)或句点(.)符号来修改文件或目录的组所有权,如下所示的命令所示:

$ chown :group <filename_or_directoryname>

以下截图显示了使用 chown 命令将 myfile 的组更改为 jack 的过程:

使用 chown 修改用户和组的所有权

chown 命令还可以通过以下任一语法同时修改文件的所有者和组:

$ chown    owner:group    <filename_or_dirname>
$ chown    owner.group    <filename_or_dirname>

chown 命令可用于将名为 myfile 的文件的所有者更改为 root,并将该文件的组更改为 wheel,如下所示的截图所示:

使用 chgrp 修改组所有权

chgrp 命令也用于修改文件或目录的组。与前面的命令 chown 不同,chgrp 只能修改组所有者,不能修改用户所有者和组所有者。此命令的语法如下:

$ chgrp    <new_groupname>    <filename_dirname>

chgrp 命令可用于将 myfile 文件的组更改为 jack 组,如下所示的截图所示:

特殊权限

除了默认适用的基本权限集外,Linux 还拥有一些特殊/高级权限集,偶尔用于增强某些功能。这些权限适用于文件(主要是可执行文件)和目录。包括 setuid、setgid 和粘滞位(sticky bit)。

修改文件的特殊权限

Setuid 和 setgid 是应用于可执行文件的两种特殊权限。

如果 setuid 应用于一个可执行文件,这意味着如果该文件作为程序执行,它将以文件的用户身份运行,而不是以运行程序的用户身份运行。

同样,当 setgid 应用于文件时,文件将以文件的组身份运行,而不是以运行程序的组身份运行。

passwd 命令在 Linux 系统中默认应用 setuid,如下所示的截图所示:

chmod 命令可用于向名为 myscript 的脚本文件添加 setuid,如下所示的命令行所示:

$ ls -l myscript
$ chmod u+s myscript

or

$ chmod 4755 myscript
$ ls -l myscript

可以使用chmod命令为名为myscript的脚本文件添加setgid权限,如下所示的命令行所示:

$ ls -l myscript
$ chmod g+s myscript

or

$ chmod 2755 myscript
$ ls -l myscript

修改特殊权限,适用于目录

sticky bit和setgid是应用于特殊目录的特殊权限。

使用粘滞位

sticky bit特殊权限用于对文件删除进行限制。当在目录上设置粘滞位时,只有文件的所有者和根用户可以删除该目录中的文件,例如:

在 Linux 系统中,/tmp文件夹默认应用了粘滞位,如下图所示:

以下示例演示了如何使用chmod命令为目录添加粘滞位(sticky bit)权限:

$ ls -ld mydir
$ chmod o+t mydir

or

$ chmod 1775 mydir
$ ls -ld mydir

使用 setgid

setgid特殊权限用于启用从父目录继承组权限。当在目录上设置setgid时,在该目录中创建的文件将从父目录继承组权限,而不是从创建文件的用户继承。它通常用于协作(共享)目录,以自动将文件的组从默认的用户私有组更改为共享组。

以下命令行用于查看目录的现有权限:

$ ls -ld mydir

以下示例演示了如何使用chmod命令为目录添加setgid权限:

$ chmod g+s mydir
or
$ chmod 2770 mydir
$ ls -ld mydir

下面是列出特殊权限及其对文件和目录影响的表格:

特殊权限 第四位数字权重 对文件的影响 对目录的影响
setuid (u+s) Setuid = 4 文件以拥有该文件的用户身份执行,而不是运行该文件的用户身份 无效
setgid (g+s) Setgid = 2 文件作为拥有该文件的组来执行 启用组继承。在该目录中创建的文件将继承该目录的组所有者
sticky bit (o+t) 粘滞位 = 1 无效 只有根用户或文件所有者可以删除带有粘滞位的目录中的文件

在设置这些特殊权限时需要格外小心,因为错误设置(使用)setuid和setgid在二进制文件上可能导致权限提升。这种情况可以帮助攻击者通过普通用户账户获取根账户的访问权限。

管理默认权限

文件从创建它们的用户或进程中获取默认权限。如果文件是使用文本编辑器创建的,则它将对所有人具有读写权限,但没有可执行权限。同样,通过编译器创建的二进制可执行文件通常具有可执行权限集,因为它们是为了执行而创建的。

理解 umask

默认的文件和文件夹权限由umask程序设置。没有任何参数的umask命令会显示当前的umask值。加上新的八进制值作为参数,umask命令会设置新的值。以下命令行用于查看用户的现有umask值:

$ umask

普通用户和 root 用户的umask值不同,这决定了文件和目录的默认权限。以下示例说明了系统中普通用户和 root 用户的不同umask值:

  • 在终端中以 root 用户执行umask命令,查看 root 账户的umask值,如下图所示:

  • 要查看student用户的umask值,首先切换到student用户账户,然后执行umask命令,如下图所示:

对于文件,最大默认值通常是666(普通文件默认不需要设置执行权限),对于目录,最大默认值是777(因为目录需要执行权限来使用cd命令)。umask值是从最大默认八进制值中减去的,用来决定文件和目录的默认权限。

例如,让我们理解一下umask值0022,它是 root 账户的默认值。这意味着从文件和目录的最大权限中去除组和其他用户的写权限。因此,文件的默认权限将是644,目录的默认权限将是755。类似地,umask值0002,这是普通用户账户的默认值,意味着从文件和目录的最大权限中去除其他用户的写权限。因此,文件的默认权限将是664,目录的默认权限将是775。

当为用户设置新的umask值时,如果umask命令的参数少于三位八进制数字,则参数部分会自动补充零。

管理文件上的 ACL

标准的 Linux 文件权限适用于文件所有者、文件所属组或系统中的其他所有人。使用标准权限时,我们不能为单个文件设置多个用户或多个组的不同权限。这种精细的控制可以通过 Linux 中的 ACL 来实现。我们可以为同一个文件设置多个用户或多个组的权限。

文件所有者或 root 可以对单个文件或目录设置 ACL,前提是文件系统启用了 ACL 支持。CentOS 7 的默认文件系统是XFS,它内置了 ACL 支持。虽然并非所有应用程序(如tar)都支持 ACL,但它仍然是 Linux 系统中的一个强大功能。

查看 ACL 权限

使用ls -l命令,我们可以查看标准权限,并判断文件或目录是否应用了 ACL。如果权限的第十个字符是+符号,则表示该文件或目录应用了 ACL。

如果文件上存在加号(+)符号,则表示用户权限代表用户的 ACL 设置,组权限代表 ACL 掩码(而不是组所有者设置),其他权限则为其他 ACL 设置。以下截图显示了如何检查文件是否应用了 ACL 权限:

如果文件应用了 ACL,则使用 chmod 修改其组权限会改变 ACL 掩码,而不是组所有者权限。

使用 getfacl

要查看文件或目录上的 ACL,可以使用getfacl命令。其语法如下图所示:

getfacl命令也可以用于将应用于文件或目录的 ACL 导出到文件中,如以下命令行所示:

$ getfacl -R /data > file.acl

可以通过从文件导出 ACL 并使用setfacl命令应用,如以下命令行所示:

$ setfacl --set-file=file.acl

ACL 掩码

ACL 掩码用于设置文件的组所有者、命名用户和命名组的最大有效权限。所有者或其他用户的最大权限是通过chmod设置的,而不是由 ACL 掩码控制。

使用setfacl命令可以在文件上设置 ACL 掩码,如下所示:

$ setfacl   -m    m::r    filename

使用getfacl命令可以查看 ACL 掩码,如下所示:

$ getfacl     filename

getfacl命令会在被掩码限制的条目前显示字符串#effective:。每当使用chmod更新组权限时,它会自动更新。

下表列出了 Linux 系统中的用户类型及其相应的 ACL 优先级:

用户类型 ACL 优先级
所有者用户 应用 ACL 权限
命名用户 应用 ACL 权限(应等于或小于 ACL 掩码)
组 应用 ACL 权限(应等于或小于 ACL 掩码)
命名组 应用 ACL 权限(应等于或小于 ACL 掩码)
其他人 应用 ACL 权限

修改 ACL 权限

ACL 使用与 chmod 相同的标准文件系统权限表示。

下表列出了符号及其在 ACL 中对应的权限表示:

符号 权限
r 读取
w 写入
x 执行
- 该权限不存在
X 表示执行权限应设置在目录上,而不是常规文件上

使用 setfacl

setfacl命令与-m选项一起使用,用于修改或添加新的 ACL 到文件或目录。例如,可以使用chmod或setfacl来设置文件所有者权限。如果在setfacl的用户部分未指定命名用户,则该权限应用于文件所有者,如以下命令所示:

$ ls -l file1
$ setfacl -m u::rwx file1

使用用户名或 UID 在文件上设置命名用户 ACL,如以下命令所示:

$ setfacl -m u:jack:rwx file1

如果在 ACL 中未指定命名组,则该 ACL 适用于组所有者,如以下命令所示:

$ setfacl -m g::rw file1

我们可以使用组名或 GID 修改或添加命名组 ACL,如以下命令所示:

$ setfacl -m g:sam:rw  file1

我们可以使用getfacl命令的输出,并将其作为输入传递给setfacl命令来设置 ACL。在以下示例中,--set-file选项使setfacl命令能够从文件或stdin(-)读取输入,如以下命令所示:

$ getfacl file1 | setfacl  --set-file=- file2

我们可以使用-R选项递归地设置目录的 ACL。X选项通常与递归一起使用,以便目录将获得可执行权限,这样在递归设置 ACL 权限时,能避免意外地给文件添加可执行权限:

$ setfacl -R -m u:jack:rX dir1

我们可以在目录上设置默认 ACL,以便对所有新文件和子目录启用 ACL 继承,使用-d选项或在setfacl命令前加上d:,如以下命令所示:

$ setfacl -m d:u:jack:rwX directory

要删除默认 ACL,请使用-x选项并加上d:,如以下命令所示:

$ setfacl -x d:u:jack:rwX directory

删除 ACL

setfacl命令也可以与-x选项一起使用,删除任何用户或组应用的 ACL。与设置 ACL 时的不同之处在于,我们在删除时不指定权限。以下示例演示了如何使用setfacl命令删除文件file1上应用于用户 jack 和组 sam 的 ACL:

$ setfacl -x  u:jack,g:sam  file1

要从文件或目录中删除所有 ACL,可以使用-b选项,如以下命令所示:

$ setfacl -b file1

总结

本章我们首先学习了 Linux 系统中不同类型的权限以及如何使用数字和符号管理它们。接着我们学习了如何使用chown和chgrp命令管理文件所有权。然后我们了解了可执行文件和目录的特殊权限。之后我们学习了如何管理默认权限。最后,我们探讨了如何在 CentOS 7 上查看、设置和删除文件及目录的 ACL。

在下一章中,我们将学习 CentOS 7 中的进程管理。进程管理是管理系统资源所必需的基本技能,它将为优化系统性能奠定坚实的基础。

第六章:进程管理

进程在运行系统中访问多个资源。进程管理对于有效管理这些资源并保持系统平稳运行至关重要。在本章中,你将学习如何查看在 Linux 系统上运行的进程,以及如何通过命令行进行交互式管理。然后,你将学习如何使用命令行控制在 Linux 系统上运行的不同程序。你还将学习如何使用信号与不同的进程进行通信,以及如何在运行系统中修改它们的优先级。

在本章中,我们将涵盖以下主题:

  • 理解进程

  • 查看当前进程

  • 使用信号与进程进行通信

  • 监控进程和负载平均值

  • 使用 nice 和 renice 管理进程的优先级

  • 在命令行中控制作业

理解进程

本节介绍与进程相关的各种概念,如进程的类型、状态、属性等。进程管理是所有类型的 Linux 系统用户应掌握的重要技能。

定义进程

进程是程序执行的实例。它不同于程序或命令,因为单个程序可以同时启动多个进程。每个进程使用多个资源,如下所列:

  • 内存中的地址空间

  • 每个进程都有一些安全属性,如所有权、权限等。

  • 每个进程都有一个状态

  • 每个进程都有本地和全局环境变量

  • 每个进程都有一个调度上下文

  • 每个进程都有分配的资源,如文件描述符、网络端口等。

  • 内核通过为每个进程分配一个独特的进程 ID(PID)编号来跟踪每个进程。

  • 用户的程序通过一个名为 /proc/PID 的目录访问每个进程的信息,该目录由内核维护。

Linux 系统上的进程创建

CentOS 7 上的所有进程都是第一个系统进程的后代,该进程被称为systemd。一个现有进程(父进程)通过 fork 系统调用复制自己的地址空间,创建一个新的进程(子进程)结构。每个新进程都会被分配一个独特的 PID,用于跟踪进程状态、CPU 使用率、内存使用率等特征。PID 通常在创建新进程时按升序分配。PID 1 被分配给 systemd 进程。PID 和PPID(即父进程 ID)是每个在 Linux 系统上运行的进程的属性。

PPID 是启动子进程的父进程的 PID。如果父进程死亡,该进程被称为孤儿进程。长期以来,孤儿进程由 init(PID=1)进程收养。然而,在现代内核中,kthread(PID=2)是孤儿子进程的收养进程。

线程 ID(TID)号与单线程进程的 PID 相同。对于多线程进程,所有线程共享相同的 PID,但每个线程有不同的 TID。

进程类型

根据任务的不同,进程有不同的类型。以下子节描述了一些 Linux 系统上常见的进程类型。

交互式进程

这种类型的进程由用户启动,可以通过命令行或图形用户界面启动,如 Bash shell、Firefox、top 命令等。

批处理进程

这种类型的进程通常在终端中调度运行,并在稍后的阶段断开与终端的连接。例如,updatedb 就是一个例子。

守护进程

这些进程在系统启动时自动启动,并持续运行,直到关机或在中途被手动停止。它们在后台不断等待用户或系统请求。按照惯例,大多数守护进程的名称以字母 d 结尾,如 httpd、named、mysqld 等。

线程

线程也被称为 轻量级进程(LWPs)。每个线程都有一个主进程,线程与主进程共享内存和其他资源。每个线程由内核调度并独立运行。线程可以随时结束,而不会终止整个进程,进程也可以随时创建新的线程。例如,当我们在 Firefox 浏览器中打开多个标签页时,浏览器会创建多个线程,每个线程独立运行。

内核线程

这些是由内核启动并使用的内核任务,用户对它们的控制非常有限,例如 kthreadd。

进程状态

Linux 是一个多任务操作系统,每个 CPU 核心在任何时刻执行一个进程。这个调度过程(不断地将进程从 CPU 上切换下来和分配 CPU 时间,依据优先级)是内核的关键功能之一。基于此,进程被分配一个状态,如运行、休眠、停止等,并且随着情况的变化而不断变化。

下表列出了 Linux 进程状态及其标志和描述:

进程状态名称 标志 内核定义名称 描述
运行中 R TASK_RUNNING 在此状态下,进程要么正在 CPU 上执行,要么在队列中等待运行。这个状态也被称为 可运行,当进程准备好运行并在队列中等待时。
休眠中 S TASK_INTERRUPTIBLE 在此状态下,进程正在等待某个事件完成。接收到信号时,进程将返回到运行状态。
D TASK_UNINTERRUPTIBLE 在此状态下,进程不会响应信号。它仅在特定条件下使用,通常与 I/O 相关,当不希望中断时使用。
K TASK_KILLABLE 在此状态下,进程处于休眠状态,并且只会响应 kill 信号以退出。
停止 T TASK_STOPPED 该状态发生在进程被作业控制信号停止时。
僵尸 Z EXIT_ZOMBIE 僵尸或死掉的进程状态是指进程已终止,但其条目没有被相应的父进程从进程表中移除。

查看当前进程

每个在 Linux 系统上运行的进程都有各种属性,如 PID、PPID、进程消耗的 CPU 时间、进程的物理和虚拟内存消耗等。所有这些信息都可以在操作系统的进程表中找到。当在多用户环境中工作时,可能会发生某个用户启动的进程过度消耗 CPU 周期。因此,管理进程和计算机资源的效率至关重要。为此,我们需要识别进程的类型并调整其优先级,甚至在必要时终止它们。本节描述了多种有助于查看进程及其属性的命令。

列出正在运行的进程

ps(即进程状态的缩写)用于列出进程表中当前的进程信息。它类似于 Windows 中的tasklist命令,用于在命令提示符下列出 Windows 正在运行的任务。

ps 命令

Linux 版的ps命令支持三种格式,如下所示:

  • Unix (POSIX)标准:在此格式中,选项可以组合使用,并且前面带有连字符

  • BSD 标准:在此格式中,多个选项可以组合使用,但不以连字符符号为前缀

  • GNU 标准:在此格式中,使用长选项,且前面带有两个连字符符号

ps命令的各种用法在以下小节中进行了描述。

显示当前 shell 运行的进程

使用ps命令,如下所示的截图,列出当前 shell 运行的进程:

输出显示数据行,包含以下列:

命令 描述
PID 正在运行的进程的进程 ID
TTY 进程运行的终端类型
TIME 进程及其启动的子进程所消耗的累积 CPU 时间
CMD 当前进程运行的命令

按用户显示所有进程

可以使用ps命令和-u选项通过用户过滤进程,如下所示的命令行:

$ ps -u student

以不同格式显示所有进程

ps命令可以以不同的格式显示系统中所有正在运行的进程,如下所示:

以 Unix 格式显示系统中所有正在运行的进程。

ps命令可以使用-A或-e选项显示系统中所有正在运行的进程,以简单的 Unix 格式,如下所示的命令行:

$ ps -A
or
$ ps -e

ps命令可以通过使用-e选项显示所有正在运行的进程,并使用-f选项显示每个进程的完整细节,以 Unix 格式显示,如下所示的命令行:

$ ps -ef

执行前述命令后的输出如下所示:

在前面的示例中,我们已将ps命令的输出限制为仅显示前五行,使用了head命令。在后续示例中,我们使用了相同的技巧来限制ps命令的输出以便进行演示。

输出显示带有以下列的数据行:

命令 描述
UID 执行命令的用户 ID
PID 命令的进程 ID
PPID 启动该命令的父进程
C 进程拥有的子进程数量
STIME 进程的启动时间
TTY 与进程关联的终端;如果进程没有附加到终端,你将看到一个问号?
TIME 进程及其子进程消耗的累计 CPU 时间
CMD 启动该进程的命令
使用-F选项与-e选项一起使用($ ps -eF)将列出更多的列:
PSR 分配给进程的处理器编号
SZ 给定进程的物理页面总内存大小
RSS 常驻内存集大小,表示进程实际占用的物理内存大小

使用 BSD 语法显示系统中所有正在运行的进程。

ps命令可以与 aux 选项一起使用,以 BSD 语法显示所有运行的进程,如下所示的命令行。在这里,选项a列出所有附加到终端的进程,选项u列出进程的用户,选项x列出所有未与终端关联的进程:

$ ps aux

执行前述命令后的输出如下所示:

输出显示带有以下列的数据行:

命令 描述
USER 与该进程关联的用户名称
PID 分配给该进程的唯一数字进程 ID
%CPU 进程使用的 CPU 百分比(进程运行的时间长度除以进程使用的总 CPU 时间)
%MEM 进程使用的 RAM 内存百分比(使用的内存除以总可用内存)
VSZ 表示虚拟内存大小,以 KiB 为单位
RSS 常驻内存集大小,表示进程实际占用的物理内存大小
TTY 控制该进程的终端;如果进程没有附加到终端,你将看到?
STAT 显示以下进程状态:R:运行中S:可中断休眠D:不可中断休眠T:已停止Z:僵尸进程<:高优先级N:低优先级L:内存中有页面被锁定s:会话领导进程l:多线程+:前台进程
START 进程启动的日期或时间
TIME 进程及其启动的子进程所消耗的累计 CPU 时间
CMD 启动进程时使用的命令

基于不同参数排序进程

在本节中,我们将展示不同的示例,向您展示如何根据不同的参数使用ps命令对进程进行排序。每个示例的输出将在随后的截图中显示。

  • 按 CPU 利用率升序排序进程:

  • 按内存利用率升序排序进程:

  • 通过单一命令结合 CPU 和内存利用率进行排序:

如果进程表中有僵尸进程条目,它将显示为退出或无效。

按用户显示进程

要按用户过滤进程,-u选项后跟用户名。可以提供多个用户名,用逗号分隔。以下示例使用ps命令仅列出由用户 Apache 启动的进程,如下图所示:

按进程名显示进程信息

要按进程名列出进程信息,使用-C选项,后跟准确的进程名,如下图所示:

按 PID 显示进程详情

使用 PID 显示进程信息时,使用-p选项,后跟进程的 PID,多个 PID 之间用逗号分隔,如下图所示:

以树形结构显示进程层次

要显示进程之间的父子关系,可以使用--forest选项,如下图所示:

显示父进程的子进程

要显示某个父进程的子进程,可以使用--ppid选项,后跟主进程的 PID。主父进程由 root 拥有,子进程由父进程分叉并由父进程拥有。以下示例展示了如何使用ps命令显示指定父进程 PID 的子进程:

显示进程的线程

要显示进程的线程,-L选项与ps命令一起使用,如下图所示:

输出显示了一行行数据,包含多个列,所有列都已在前面的示例中介绍,除了 LWP 列(表示 TID)和 NLWP(即 Number of Lightweight Processes 的缩写,表示进程中线程的数量)。

如果已知进程名称,则显示该进程的 pid

若要仅打印已知名称的进程的 PID,可以使用 -C 选项,后跟精确的进程名称,并使用 -o 选项,后跟 pid=,如下所示:

你可以从 ps 命令的手册页中查找 Unix 标准和 BSD 标准中所有标签的含义以及各种进程状态描述。

使用 pstree 命令

此命令用于以层次格式显示父子关系。此命令的输出与 ps axjf 命令和 ps -ef --forest 命令的输出非常相似,如以下命令行所示:

$ pstree

以下截图展示了使用 pstree 命令显示单个进程的 PID 树状层次结构:

执行给定命令行来显示用户进程的树状层次结构:

$ pstree -p student

执行前述命令时,分配给每个进程的 PID 将显示在每个进程名称后面的括号中。

查找正在运行的进程的 PID

很多时候,我们需要识别一个 PID 来管理它,例如,如果你需要停止某个进程的执行。有时,你可能需要改变进程的优先级。因此,最常用的方法是通过 PID 与进程进行通信。本节介绍了多种用于查找正在运行的进程 PID 的命令。

使用 pgrep 命令

pgrep 命令用于根据进程的名称和其他属性查找当前正在运行的进程,并显示匹配的进程 PID。其语法如下:

$ pgrep    [options]    pattern

以下是解释如何使用 pgrep 命令的示例:

要列出命令名为 sshd 的进程(该进程也由 root 所有),可以按如下命令行执行:

$ pgrep -u root sshd

要列出由用户 root 或 daemon 所拥有的进程,执行如下命令行:

$ pgrep -u root,daemon

pgrep 命令可用于通过指定包含进程名称的模式来列出进程。以下命令行将查找名为 Firefox 的进程的 PID:

$ pgrep firef

以下示例展示了如何使用 pgrep 命令列出用户 student 的所有进程:

$ pgrep -U student

pidof

pidof 命令可用于查找正在运行的程序的进程 ID,如果提供给 pidof 命令的参数是精确的进程名称,如下所示:

$ pidof bash
$ pidof firefox

使用 ps 命令与 grep

实际上,很难记住 Linux 系统上正在运行的进程的准确名称。在无法记住进程精确名称的情况下,pidof 命令不会返回进程的 PID。此时,可以将 ps 命令的输出作为输入,使用 grep 过滤器查找所需的进程名称,命令行如下所示:

$ ps aux | grep <process_name>
$ ps aux | grep sshd

输出的第二列包含了被过滤进程的 PID。

与进程通过信号进行通信

进程通过信号进行相互通信。我们也可以使用 kill、pkill 或 killall 命令与进程进行通信,传递不同的信号。

定义信号及其类型

信号是一种软件中断,作用于进程。信号也可以看作是需要处理的特定事件的通知。Kill、pkill 和 killall 是用来将这些信号发送到进程的程序。在 Linux 系统中,所有的信号名称都以 SIG 开头。以下表格中描述的信号编号在不同的 Linux 硬件平台上可能会有所不同,但信号名称和含义始终保持一致。

以下表格列出了用于进程管理的常见信号及其描述:

信号编号 信号名称 含义 描述
1 SIGHUP 挂起 当控制终端挂起(用户离开时终端关闭)时发送。
2 SIGINT 键盘中断 用于通过键盘组合键 Ctrl + C 终止程序。
3 SIGQUIT 键盘退出 用于通过键盘组合键 Ctrl + D 终止程序。
9 SIGKILL 强制终止 强制、突然地终止程序。无法被阻塞、忽略或处理。
15(默认) SIGTERM 优雅终止 优雅地终止程序。此信号可以被阻塞、忽略或处理。它是 kill 命令发送的默认信号。
18 SIGCONT 继续 告诉已停止的进程恢复运行。
19 SIGSTOP 停止 暂停一个进程。此信号无法被阻塞或处理。
20 SIGTSTP 键盘暂停 用于通过键盘组合键 Ctrl + Z 暂停进程。此信号可以被阻塞、忽略或处理。

kill 命令用于列出 Linux 系统支持的所有信号,如以下截图所示:

每个信号都有一个默认的动作,例如终止进程、停止进程、继续已停止的进程等。

向进程发送信号

向进程发送信号的方法有多种。最常见的一种是使用键盘中断,如 Ctrl + C、Ctrl + D 等。另一种方法是使用 kill、killall 和 pkill 命令。

使用 kill 命令按 PID 向进程发送信号

kill命令通过 PID 向进程发送信号。与其名称相反,kill命令可用于向进程发送任何信号。kill命令发送的默认信号是SIGTERM,例如信号编号15。kill命令的语法如下:

$ kill   -<signal_name_or_signal_number>    PID_OF_PROCESS

以下是一些示例,解释kill命令的用法:

  • 要发送默认信号以优雅地终止进程,请使用以下命令:
$ kill PID
  • 要使用信号名称终止进程,请使用以下命令:
$ kill -SIGTERM PID
  • 要使用信号编号终止进程,请使用以下命令:
$ kill -15 PID
  • 要强制终止进程,请使用以下命令之一:
$ kill -SIGKILL PID
or
$ kill -9 PID

这类似于我们在 Windows 的任务管理器中执行的操作,当我们右键点击任务管理器中的进程名并传递结束进程命令时:

  • kill命令可用于挂起/停止一个进程,并在其在前台运行时将其发送到后台。可以使用以下任一命令来实现:
$ kill -SIGTSTP  PID
or
$ kill -20 PID
  • 如果进程已被停止,使用以下任一命令来恢复进程:
$ kill -SIGCONT PID
or
$ kill -18 PID

按名称向多个进程发送信号

我们还可以使用killall命令和pkill命令,通过进程名称向一个或多个进程发送信号,具体内容将在以下小节中讨论。

killall

killall命令用于在匹配以下条件之一时,向一个或多个进程发送信号:

  • 命令:匹配精确的进程名称

  • 所有者:匹配进程所有者的精确名称

  • 所有系统:系统范围的进程

其语法如下:

 $ killall    <process_name>
 $ killall   -<signal>    <process_name>
 $ killall   -<signal>   -u    <username>    <process_name>

pkill

pkill命令还可以在匹配一组条件时,向多个进程发送信号,以下是一些示例:

  • 使用带有命令模式的pkill:pkill命令可以向匹配的进程名称发送信号,如下所示:
$ pkill   <command_name_pattern>
 $ pkill   -<signal_name_or_signal_number>   <command_name_pattern>

下面的截图展示了使用单个pkill命令向多个sleep进程发送信号的示例:

  • 使用带有 UID 的pkill命令:pkill命令可以通过指定 UID,将信号发送给由指定 Linux 用户帐户拥有的进程,具体语法如下:
$ pkill    -u     <username_or_uid>     <command_pattern>
  • 使用带有 GID 的pkill命令:pkill命令可以通过指定 GID,将信号发送给由指定 Linux 组帐户拥有的进程,具体语法如下:
$ pkill    -g     <groupname_or_gid>    <command_pattern>
  • 使用带有父 PID 的pkill命令:pkill命令可用于向指定父进程的所有子进程发送信号,具体语法如下:
$ pkill    -P   PPID    <command_pattern>
  • 使用带有终端名称的pkill命令:pkill命令可以向从特定控制终端运行的进程发送信号,具体语法如下:
$ pkill   -t   <terminal_name>   -U   UID   <command_pattern>

监控进程和负载平均值

负载平均值是给定时间段内每个 CPU 的负载平均值。它考虑了以下因素:

  • 积极运行的进程(包括将每个线程视为独立的、单独的任务)在 CPU 核心上运行。

  • 可运行的进程,等待 CPU 变得可用。

  • 睡眠中的进程,例如,等待某种资源(通常是磁盘 I/O 或网络 I/O)变得可用。

  • Linux 将每个物理 CPU 核心和微处理器超线程视为独立的执行单元,并将其称为独立的 CPU。每个 CPU 都有一个独立的请求队列。我们可以使用以下命令来计算系统 CPU 的总数:

    $ grep "model name" /proc/cpuinfo | wc -l
    

理解 Linux 中的负载平均值

进程的负载平均值可以通过使用w、uptime或top命令来查看,也可以在图形界面模式下通过 gnome-system-monitor 查看。这些命令通过结合所有 CPU 在过去 1、5 和 15 分钟内的负载平均值来显示负载。

uptime

uptime命令告诉你系统已经运行了多长时间。不过,它同时还提供了其他有用的信息,例如当前登录的用户数以及过去 1、5 和 15 分钟内的系统负载平均值:

当我们有多个 CPU 时,负载平均值将根据前面的截图进行按 CPU 数量的划分。短时间内负载的增加并不成问题,但如果过去 5 分钟或 15 分钟的负载平均值持续上升,则可能需要关注。

w

w命令用于显示当前登录到机器的用户及其正在运行的进程的信息。输出的第一行(标题)与我们在uptime命令输出中看到的相同。以下截图展示了w命令的一个示例:

输出显示了包含以下列的数据行:

命令 描述
USER 用户登录名
TTY 控制终端类型,在 GUI 中显示为 pts/N(伪终端),或在系统控制台或其他直接连接的设备上显示为 ttyN
FROM 用户登录的远程主机名
LOGIN@ 用户的登录时间
IDLE 自用户在该终端上输入命令以来的空闲时间
JCPU 所有附加到 tty 的进程的 CPU 时间消耗,包括当前在后台运行的作业
PCPU 当前进程(在WHAT字段中列出)的 CPU 时间消耗
WHAT 当前执行进程的命令行

实时交互式进程监控

ps命令提供系统上正在运行的进程的静态快照。有时,也需要对系统进行实时监控。top命令用于执行系统的实时监控。

top

top 程序提供一个每 2 秒更新一次的系统进程实时视图,直到按 q 停止执行。它显示多项信息,包括系统的运行时间、正在运行的任务列表、CPU 状态、内存状态摘要,并显示每个进程所消耗的不同资源。top 命令的执行方式如下:

$ top

执行前述命令时的输出如下面的截图所示:

输出显示了系统信息摘要,接下来是每个不同进程的信息,以行的形式排列,按 CPU 使用率从高到低排列在以下列中:

系统信息摘要
1) 第一行显示系统已运行的时间、登录用户的数量以及负载平均值。
2) 第二行显示了进程总数,后面跟着正在运行、休眠、停止和僵尸进程的数量。
3) 第三行显示各种 CPU 使用参数:
us
sy
ni
id
wa
hi
si
st
4) 第四行和第五行显示内存使用情况。第四行显示物理内存,第五行显示虚拟内存。
5) 第六行包含了按 CPU 使用率降序排列的进程信息列表的标题。它包含以下字段:
PID
USER
PR
NI
VIRT
RES
SHR
S
%CPU
%MEM
TIME+
COMMAND

top 命令类似于 Linux 中的命令行任务管理器。使用top,我们可以进行交互式监控并管理正在运行的进程。还有一些单键快捷键可以管理运行中进程的不同属性。

以下表格列出了用于管理top命令的各种键盘快捷键及其描述:

键盘快捷键(在顶部) 描述
t 切换显示汇总信息
m 切换显示内存信息
l 切换显示正常运行时间信息
1 切换显示所有 CPU 的汇总信息或单个 CPU 的汇总信息
H 切换在任务的汇总信息中显示线程
s 更改屏幕刷新率(以秒为单位)
A 按最顶级资源消耗者排序进程列表
r 重设(修改优先级)一个选定进程,通过提供 PID 和 nice 值
k 向特定进程发送信号(默认信号是终止),通过提供 PID 和信号编号
f 打开top命令的配置界面
M 按内存使用量降序排序进程
P 按 CPU 利用率降序排序进程
? 或 h 显示交互式键盘快捷键的帮助信息
U 筛选用户名显示
q 退出
Enter, 空格键 立即刷新显示的信息

以下是一些示例,用于解释top命令的使用:

  • 使用以下命令仅显示指定pid的进程状态:
$ top -p pid
  • 使用以下命令指定连续屏幕刷新的延迟时间:
$ top -d 2
  • 使用以下命令仅显示top命令在指定迭代次数下的输出:
$ top n <number>

你可以了解更多关于高级工具的信息,例如htop,它是一个进程监控工具,允许你垂直和水平滚动以查看更多的进程。

使用 nice 和 renice 管理进程的优先级

Linux 是一个多任务操作系统。在任何给定的时间,系统上都有多个进程在运行或等待队列中等待,但单个 CPU 实际上一次只能执行一个任务。如果进程队列过长,可能会导致一些更重要的进程花费更多时间在等待上,而不是执行。因此,为了解决这个问题,Linux 允许我们设置和修改进程的优先级。低优先级进程会获得更少的 CPU 时间,而高优先级进程则会获得更多的 CPU 时间。通过使用nice和renice命令,我们可以管理进程的优先级。

理解优先级

进程的优先级被称为它的nice值(或友好度)。它告诉你进程在 CPU 上的友好程度(使用的 CPU 周期数)。它的值从-20到19不等。较低的 nice 值代表较高优先级的进程,将占用更多的 CPU 周期,而较高的 nice 值代表低优先级的进程,可以等待更长时间且占用更少的 CPU 周期。因此,-20表示最高优先级,19表示最低优先级。新进程的默认值通常是0,它继承自父进程。

修改优先级

为 CPU 密集型进程分配低的 nice 值,即更高的优先级,会影响在同一 Linux 系统上运行的其他进程的性能。因此,只有 root 用户才被允许为进程分配更高的优先级,例如,为正在运行的进程设置负的 nice 值。

普通用户只能降低自己进程的优先级,即他们只能为给定进程设置一个比现有 nice 值更大的正值。

查看进程的优先级

在 CentOS 7 中,可以使用不同的命令来查看进程的优先级,如下所示:

  • 使用 gnome-system-monitor 在图形界面模式下显示 nice 值。这是 CentOS 7 中的图形任务管理器。可以通过按下应用程序 | 系统工具 | 系统监视器来调用:

  • top命令也可以用来显示进程的优先级。它显示两列,分别为 NI(显示进程的 nice 值映射)和 PR(显示内核中优先级值的映射,表示更大的优先级队列)。

  • ps命令也可以通过使用o选项来显示nice级别,打印所选列,其中也包括 nice 字段,如下图所示:

如果在ps命令的输出中显示了负号(-),则意味着该进程正在以不同的调度策略运行,具有更高的优先级。

修改新进程的优先级(nice 值)

通常,当进程启动时,它会获得默认的优先级值 0。nice 命令用于以不同的优先级启动进程。其语法如下:

$ nice   -n   <NICELEVEL>   <command>

使用nice命令修改进程优先级的示例如下图所示:

root 用户可以设置 nice 值在(-20 到 19)之间,而非特权的普通用户只能设置 nice 值在(0 到 19)之间。

修改正在运行的进程优先级(renice)

renice命令用于修改已存在进程的 nice 值。其语法如下:

$ renice    -n    <NICELEVEL>   <PID’s>

在以下截图中,普通用户试图通过分配负值来提高进程优先级,因此他们收到了“权限拒绝”的提示,正如下面截图所示:

现在,当普通用户通过分配正值来降低进程优先级时,会立即生效,如下图所示:

除了renice命令外,top命令也可以用来修改正在运行的进程的 nice 值。使用以下步骤通过top命令修改进程优先级:

  1. 调用top命令

  2. 按下键盘上的 r 键,在 top 命令的当前交互会话中弹出设置新 nice 值的选项

  3. 输入新的nice值和 PID,然后按Enter键

在命令行中控制作业

Linux 支持在前台和后台执行程序。这个特性允许你在单个 Shell 实例中运行多个程序。这个特性称为作业控制或作业管理。

了解与作业管理相关的不同术语

本节描述了与终端上的作业管理相关的各种术语。

作业管理及其关联的控制终端

作业是从终端窗口启动的命令。每个作业可以作为独立的后台程序运行,或作为附加程序从终端运行(这里也称为控制终端)。ps命令中的TTY字段用于显示与程序关联的控制终端名称。

一些程序,例如守护进程(系统服务),是由系统启动的,并且没有任何控制终端。因此,这些程序不被视为作业的一部分,不能在前台运行。此类程序在ps aux命令的TTY字段中显示为?。

当程序作为前台进程从终端启动时,终端无法用于其他任何操作,因为它正在执行该前台进程。例如,以下命令:

$ sleep 1000

执行前面的命令后,终端将无法响应任何其他程序,因为它正在前台控制sleep程序,持续时间为1000秒。

前台进程或作业

前台进程或作业是直接从 Shell 执行的进程(这里也称为控制终端)。只要该前台作业正在运行,其他进程必须等到它完成才能访问 Shell。

这种启动程序的方法是可以的,只要程序运行时间较短并且能够在短时间内完成。如果从 Shell 中以前台方式启动一个需要很长时间(比如需要几个小时完成)的程序,它将使该 Shell 在这段时间内无法使用。这种做法不适合用于命令执行。

前台进程在使用ps命令查看其详细信息时,会在其状态后添加+符号。加号+表示它处于前台进程组中。

在一个终端中启动sleep命令作为前台进程,如以下命令行所示:

$ sleep 1000

以下图像列出了所有进程,并使用grep命令对它们进行过滤,以显示命令名称中包含 sleep 的进程列表:

如果你想中断一个正在运行的前台程序,可以使用Ctrl + C(从键盘中断)。

后台进程或作业

对于需要较长时间完成的程序,将其作为后台进程(作业)启动是理想的做法。这可以释放 Shell,使其可用于其他任务。在程序作为后台作业运行时,我们可以在终端中执行其他命令。

默认情况下,所有程序都是作为前台任务从终端执行的。要从终端启动后台作业,只需在命令末尾添加一个“和”符号。例如,从终端启动sleep命令作为后台任务,如下图所示:

将前台进程挂起到后台

我们可以通过以下两个步骤将前台进程移至后台:

  1. 首先,按下Ctrl + Z,将进程移到后台并使其进入 Stopped 状态

  2. 第二,输入bg命令,将最后一个后台进程的状态从Stoppedas改为 Running,如下图所示:

管理后台作业

通过在命令末尾加上&符号,可以将程序启动为后台进程。启动后台程序时,会显示作业 ID(该会话唯一)和后台进程的 PID,如下图所示:

使用jobs命令显示与 Shell 相关的后台作业。jobs命令显示作业 ID、状态和命令名称。如果有多个后台作业,默认选择将会在前面加上+,如下图所示:

fg命令用于将后台作业通过其作业 ID 带到前台。作业 ID 和程序的%后面跟着方括号中的作业号,如下图所示:

通过首先使用Ctrl + Z在终端中挂起前台程序,然后将其发送到后台,如下图所示:

使用jobs命令并加上-l选项时,还会列出程序 ID。为了获得更多信息,我们可以使用ps命令并加上j选项,如下图所示:

使用bg命令并跟上%和作业 ID,可以将已停止的程序恢复到后台,如下图所示:

总结

在本章中,我们首先学习了什么是进程,以及在 Linux 系统中不同的进程状态和类型。接着,我们了解了 CentOS 7 中查看正在运行的进程的不同方法。随后,我们了解了进程之间如何相互通信,以及我们如何通过信号与进程进行通信。然后,我们学习了如何监控正在运行的进程,以及如何通过调整优先级值(nice 值)来管理它们的优先级。最后,我们了解了如何在命令行中管理jobs(命令),通过将一些应用程序在后台启动并将应用程序从后台切换到前台,反之亦然。

在下一章中,我们将学习 CentOS 7 中的网络概念和网络命令。我们还将学习如何通过网络执行安全的远程登录和备份。

第七章:在 CentOS 中管理网络

独立系统通常没什么用处。网络使我们能够与其他网络设备和连接的计算机交换信息和共享资源。在本章中,您将学习从命令行管理网络连接所需的基本技能。然后,您将学习如何使用 SSH(即 安全外壳)访问远程系统,以及如何使用 SCP(即 安全复制)和 rsync 工具进行安全文件传输。

本章将涵盖以下内容:

  • Linux 网络概念

  • 使用 Linux 网络命令

  • 使用 nmcli 管理网络

  • 编辑网络配置文件

  • 配置主机名和 DNS(即 域名系统)解析

  • 使用 SSH 访问远程登录

  • 在 Linux 中传输文件

Linux 网络概念

网络是由两台或更多计算机或计算设备组成的群体,通过任何通信媒介(如电缆或无线媒介)连接。这些设备可能位于相同的地理位置,也可能分布在全球各地。网络环境提供以下三项服务:

  • 使连接的设备能够相互通信

  • 使多个用户能够共享设备,如打印机、复印机、扫描仪等

  • 使文件共享和信息管理在计算机之间进行

大多数组织使用两种类型的网络:一种用于与内部员工的通信,另一种用于与外部世界的通信。内部网是用于定义组织内部网络通信的术语,互联网用于外部通信。互联网也是世界上最大的网络,通常被称为“网络的网络”。

Linux 网络中常用的术语

本节描述了用于定义计算设备和 Linux 中使用的网络术语的各种术语。

IP 地址

每个连接到网络的设备必须具有至少一个唯一地址,用于标识该设备在网络中的位置。这个地址称为 IP 地址,并且它对于将数据包从源头路由到目标非常重要。网络上的信息或数据以数据包的形式传输。每个数据包附带一个头部,包含将数据包从源头路由到目标所需的信息。IP 地址方案有两种类型,分别为 IPv4 和 IPv6。

IPv4

IPv4 是一种 32 位逻辑地址,用于计算设备通过 TCP/IP 协议栈相互通信。它通常以四个字节的十进制表示,每个字节包含 8 位,并用点分隔。每个字节的值可以从 0 到 255 之间变化。这个地址可以进一步分为两部分;例如,网络部分和主机部分:

  • 主机部分:主机部分用于标识子网中的主机。同一子网中的两个主机不能具有相同的主机部分。

  • 网络部分:网络部分用于标识子网。位于同一子网的主机可以互相通信,而无需路由器。

使用 32 位地址时,我们最多可以拥有 43 亿个唯一地址,其中许多地址被保留且不可使用。因此,为了满足未来的需求,IPv6 使用 128 位地址被创建。

IPv6

IPv6 使用 128 位进行地址分配。它以八个八位字节表示,每个字节包含 16 位,且由冒号分隔。使用 128 位提供了 3.4 × 10³⁸个唯一地址。从 IPv4 向 IPv6 的网络设备和地址迁移需要大量的理解和努力。IPv6 没有广播地址。

本章将专注于 IPv4,因为它仍然被广泛使用,并且在进行网络操作时,你会最常遇到它。

不同类别的 IP 地址

IPv4 地址分为五个公共类别:A、B、C、D 和 E,以及三个私有IP 地址类别。

公共类别

公共 IP 地址类别从 A 到 E 共有五种。这里,A、B、C 类被划分为两个部分:网络地址(简写为Net ID)和主机地址(简写为Host ID)。Net ID 用于标识网络,Host ID 用于标识网络上的主机,如下表所示:

公共类别 第 1 字节 第 2 字节 第 3 字节 第 4 字节 范围
类别 A 网络标识符 主机标识符 主机标识符 主机标识符 1.0.0.0 至 127.255.255.255
类别 B 网络标识符 网络标识符 主机标识符 主机标识符 128.0.0.0 至 191.255.255.255
类别 C 网络标识符 网络标识符 网络标识符 主机标识符 192.0.0.0 至 223.255.255.255
类别 D 多播地址 224.0.0.0 至 239.255.255.255
类别 E 保留供未来使用 240.0.0.0 至 255.255.255.254

私有类别

以下三个 IP 地址范围保留供组织内部网络的私有使用。这些 IPv4 地址可以在网络、校园等内部使用,且无法在互联网中路由。因此,如果任何数据包包含这些私有 IP 地址,路由器将丢弃它。通常,当设备在私有 IPv4 地址空间内工作时,使用 NAT 机制与公共 IPv4 地址空间进行通信。下表列出了私有 IPv4 地址类别及其地址范围,以及一些特殊 IPv4 地址,如链路本地地址和回环地址:

私有类别 地址范围 子网掩码 地址块
类别 A 10.0.0.0 至 10.255.255.255 255.0.0.0 10.0.0.0 /8
类别 B 172.16.0.0 至 172.31.255.255 255.240.0.0 172.16.0.0 /12
类别 C 192.168.0.0 至 192.168.0.255 255.255.0.0 192.168.0.0 /16
回环地址 127.0.0.0 至 127.255.255.255 255.0.0.0 127.0.0.0 /8
链路本地地址(APIPA) 169.254.0.0 至 169.254.255.255 255.255.0.0 169.254.0.0 /16

回环地址

127.0.0.1是一个特殊的地址,总是指向本地系统(localhost),并用于测试各种服务。网络127.0.0.0/8是本地系统的回环网络,它允许在单一系统上进行服务器与客户端的通信。

链路本地地址或 APIPA

如果机器连接到 DHCP 环境中,但无法从 DHCP 服务器获取 IP 地址,则使用链路本地地址或自动私有 IP 地址分配(APIPA)。这也有助于在 DHCP 服务器未连接或宕机的情况下,通过在169.254.0.0/16范围内分配 IP 地址,使同一网络中的机器之间能够建立通信。

子网掩码

子网掩码用于标识一个子网。将 32 位主机 IP 地址与 32 位子网掩码进行按位与运算,得到地址的网络部分。子网中最低的地址是主机部分全为零,它表示网络地址。 子网中最高的地址是主机部分全为一,它表示广播地址,适用于子网内的所有主机。子网掩码可以用两种形式表示。传统语法使用十进制表示网络部分,而新的语法使用 CIDR 表示法表示网络前缀(网络地址中 1 的数量)。例如,我们可以用以下两种形式表示一个 24 位子网掩码:

  • 传统形式:255.255.255.0

  • CIDR 表示法:/24

假设我们拥有以下 IP 地址和子网掩码信息:

  • 10.1.1.212 / 8

  • 192.168.1.100 / 24

现在,利用上述有限信息,我们可以找到其他相关的网络信息,如网络地址和广播地址,具体如下表所示:

拥有以下详细信息的系统的网络信息:10.1.1.212 / 8

信息描述 值
IP 地址(主机地址) 10.1.1.212
子网掩码(网络前缀) 255.0.0.0/8
网络地址 10.0.0.0
广播地址 10.0.0.255

拥有以下详细信息的系统的网络信息:192.168.1.100 / 24

信息描述 值
IP 地址(主机地址) 192.168.1.100
子网掩码(网络前缀) 255.255.255.0/24
网络地址 192.168.1.0
广播地址 192.168.1.255

网关

网关通常是用于连接两个或多个不同网络的路由器设备或计算机。在 Linux 中,它是内核路由表中的一项条目,当没有匹配的路由条目时,将使用该条目。

主机名

主机名是与机器 IP 地址关联的人类可读名称。DNS 服务器用于将主机名映射到 IP 地址,反之亦然。我们可以通过输入hostname命令(不带任何参数)查看任何机器的主机名,如下所示:

$ hostname

每台机器都有一个特殊的主机名,即与回环 IP 地址127.0.0.1关联的 localhost。此地址用于测试系统上的各种服务。

域名服务器

Nameserver 也称为DNS 服务器。DNS 服务器的目的是将主机名转换为 IP 地址,反之亦然。在 CentOS 7 中,进行 DNS 查找时有一个默认的固定文件顺序。这一顺序由nsswitch.conf文件中写入的规则管理,管理员可以进行修改。系统在解析 DNS 查询时会查找以下两个文件:

  • /etc/hosts:在将查询转发到 DNS 服务器之前,首先会查找该文件中的条目。它是一个主机名和 IP 地址映射的本地数据库。对于小型独立网络来说,它也非常有用。

  • /etc/resolv.conf:如果在/etc/hosts文件中找不到 DNS 查询的答案,则该查询将传递给/etc/resolv.conf中指定的 DNS 服务器。此文件可以通过 dhclient 更新或手动更新。

以下命令用于显示当前的 nameserver 设置:

$ cat /etc/resolv.conf

配置好 nameserver 后,可以使用 host 命令验证 DNS 连接,方法如下:

$ host www.google.com

NetworkManager

NetworkManager 是一个用于管理网络设置的 GUI 应用程序。它配有守护进程和 Gnome 小程序,提供网络状态并能快速修改设置。通过 NetworkManager 所做的更改会存储在/etc/sysconfig/network-scripts目录中,因此它会覆盖该处的任何手动更改。如果你想通过修改网络脚本文件来手动配置网络连接,那么应该禁用 NetworkManager。NetworkManager 提供了一种用户友好的方式来管理网络连接,非常适合初学者。

网络接口命名规则

传统上,Linux 中的网络接口按顺序编号为eth0,eth1,eth2等。

以下表格列出了接口的传统名称及其描述:

接口名称 描述
eth0,eth1,以此类推 以太网接口
wlan0,wlan1,以此类推 无线接口
eth0:1,eth0:2,以此类推 别名接口
ppp0,ppp1,以此类推 拨号接口
bond0 第一个绑定的网络设备
virbr0 虚拟主机的内部桥接
lo 回环接口

现在,CentOS 7 有了新的默认命名规则。接口名称基于硬件、拓扑结构和设备类型。

以下表格展示了 CentOS 7 中的网络接口命名规则:

命名规则中的字符 描述
前两个字符表示接口类型
  • en: 以太网接口

  • wl: Wlan 接口

  • ww: WWAN 接口

|

后续字符表示适配器类型
  • o: 集成适配器

  • s: 热插拔插槽

  • p: PCI 卡

  • x: MAC 地址

|

最后一个字符是数字N,表示索引、ID 或端口
  • N: 0, 1, 2 等

|

如果无法使用新的接口命名方案确定固定名称,则将使用旧的传统命名方案,例如eth0或eth1。这里给出了新的接口命名方案的示例:

  • eno1:第一个嵌入式网络接口

  • enp1s0:带有热插拔插槽索引 0 的第一个 PCI 卡网络接口

如果服务器启用了 biosdevname 功能,则此命名方案将被另一种命名方案覆盖。

使用 Linux 网络命令

本节讨论了用于显示或修改现有网络配置的各种网络命令和基本工具。

查看 IP 地址详情

在 CentOS 7 中,我们有三个主要工具用于显示设备和地址信息:

  • 较新的 IP 命令(/sbin/ip)

  • 几乎已过时的ifconfig命令,属于 net-tools 包(/sbin/ifconfig)

  • 多功能netstat命令(/usr/bin/netstat)

使用 IP 命令

ip是一个非常强大的工具,用于执行许多任务。早期,ifconfig和route等多个旧工具用于执行这些功能。ip命令的绝对路径是/sbin/ip。

以下是说明如何使用 ip 命令的示例:

  • 以下ip命令用于显示 IP 地址:
$ /sbin/ip addr show
  • ip命令还可以用于显示网络性能的统计信息(接收和发送的包、错误、丢包计数等),如以下命令行所示:
$ ip -s link show enp0s3
  • ip命令还可以用于显示路由信息,如以下命令行所示:
$ /sbin/ip route show

/sbin/ip命令还可以用于为单个设备分配多个 IP 地址,并使用别名。将多个 IP 地址绑定到单个网卡,并为其分配不同的标签在许多情况下非常有用(例如,在虚拟主机中)。别名被视为独立的接口,通常在关闭 NetworkManager 时进行配置。创建别名的命令如下:

$ ip addr add 10.1.1.250/24 dev enp0s8 label enp0s8:0。

使用 ifconfig 命令

这是一个旧的命令,用于显示或修改当前的网络接口配置。ifconfig命令现在已经过时,已被较新的ip工具取代。现在,ip addr和ip link命令被优先用来替代ifconfig,以显示网络接口信息。

以下表格列出了ifconfig的常用选项及其描述:

命令 描述
$ ifconfig 仅显示当前活动接口的配置
$ ifconfig -a 显示系统中所有接口的信息,无论它们是活动的还是非活动的
$ ifconfig eth0 显示指定接口eth0的配置
$ ifconfig eth0 up 如果网络适配器eth0处于关闭状态,则激活它。
$ ifconfig eth0 down 如果网络适配器eth0处于开启状态,则将其关闭。

ifconfig 命令可以用来为网络适配器分配 IP 地址和子网掩码。这些更改是运行时生效的,并且在重启后会丢失。以下命令行展示了如何使用 ifconfig 为接口分配 IP 地址和子网掩码:

$ ifconfig eth0 192.168.1.51/24 or
$ ifconfig eth0 192.168.1.51 netmask 255.255.255.0

一些较为初学的用户仍然发现,较旧的 ifconfig 命令相比新版本更为易用,而 ip 命令则功能更强大且灵活。

ifconfig 工具是 net-tools 包的一部分。如果该包未安装在系统上,那么在 CentOS 7 中你可能无法访问该工具。

Netstat

netstat 命令也可以用来打印接口详情。要显示所有接口的内核接口信息,可以使用 -i 选项与 -e 选项,来显示接口的扩展信息,如下所示:

$ netstat -ie 

查看路由信息

无论底层 IP 地址方案如何,在通信过程中,信息需要从一个网络上的主机传输到另一个网络上的主机。每个主机可以有多个路由表,决定如何将流量从主机路由到特定网络。路由表确保使用正确的网络接口将数据包发送到目标网络。我们还可以在路由表中定义任何中间路由器的 IP 地址,以便到达目标网络。

使用 ip route 命令

ip route 命令是新版本 ip 工具的众多功能之一。此命令可以用来显示或修改现有的 IP 路由表。我们可以使用 ip route 命令添加、删除或修改指向特定主机或网络的静态路由。

以下是展示 ip route 命令用法的示例:

  • 我们可以使用 ip route 命令显示当前的路由表,如下所示:
$ ip route 
  • ip route 命令可以用来向路由表中添加静态路由。在以下示例中,我们添加 网络路由信息,将 25.25.25.0/24 网络路由通过 eth0 接口,如下所示:
$ ip route add 25.25.25.0/24  dev  eth0

  • ip route 命令也可以用来添加主机 路由信息。在以下示例中,我们将信息添加到 IPv4 地址 15.15.15.15,并通过 eth1 接口路由:
$ ip route add 15.15.15.15 dev eth1
  • ip route 命令也可以用于从路由表中删除静态路由。在以下示例中,我们删除 网络路由信息,目标是 25.25.25.0/24 网络,如下所示:
$ ip route del 25.25.25.0/24 dev eth0
  • ip route 命令也可以用来删除 主机 路由信息。在以下示例中,我们删除通过 eth1 接口路由 IPv4 地址 15.15.15.15 的信息:
$ ip route del 15.15.15.15 dev eth0

使用 route 命令

route 命令也可以用于修改路由表。

以下是展示 route 命令用法的示例:

  • 使用 route 命令,如下所示,来显示当前的路由表:
$ route -n
  • route 命令也可以用来在路由表中添加静态路由。以下路由命令语法用于在路由表中添加网络路由信息:
$ route add -net x.x.x.x/prefix dev <devname>
  • 以下路由命令语法用于在路由表中添加主机路由信息:
$ route add -host x.x.x.x dev <devname>
  • route 命令也可以用来删除路由表中的静态路由。以下 route 命令语法用于删除路由表中的网络路由信息:
$ route del -net x.x.x.x/prefix dev <devname>
  • 以下 route 命令语法用于删除路由表中的主机路由信息:
$ route del -host x.x.x.x dev <devname> 

使用 netstat 命令

netstat 命令,也称为网络统计命令,是一个功能强大的命令,具有很多功能。此命令用于打印网络连接详细信息、内核路由表信息、接口统计信息、开放端口等。在本节中,我们仅关注如何使用 netstat 命令来获取路由表信息。

以下是说明如何使用 netstat 命令的示例。

  • 使用 netstat 命令显示带有 -r 选项的内核路由表信息,如下所示:
$ netstat -r
  • 使用 netstat 命令显示内核路由表信息,而不解析主机名或端口名,如下所示:
$ netstat -anr

netstat 是在类 Unix 操作系统和 Windows 操作系统中默认可用的少数命令之一。

网关

我们可以使用 route 命令在运行时添加或删除默认网关。默认网关告诉我们,如果路由表中没有与数据包目标 IP 地址匹配的网络或主机条目,应该将数据包发送到哪里。

以下命令行用于从路由表中删除默认网关:

$ route del default gw <ip_address_of_default_gateway> 

以下命令行用于在路由表中添加默认网关:

$ route add default gw <ip_address_of_default_gateway>

要为所有接口添加相同的永久网关,我们可以修改 /etc/sysconfig/network 文件,并添加以下条目:

GATEWAY=<ip_address_of_new_default_gateway>

要为每个接口分配不同的网关条目,我们可以修改 /etc/sysconfig/network-scripts/ifcfg-<interfacename> 配置文件,如下所示:

GATEWAY=<ip_address_of_new_default_gateway>

查看域名服务器详细信息

域名服务器或 DNS 服务器信息存储在 /etc/resolv.conf 文件中。此文件可以通过 dhclient 或 NetworkManager 更新,或者由管理员手动更新。在此文件中,我们可以指定最多三个域名服务器指令,并按优先级顺序从上到下排列。

域名服务器配置文件的内容可以通过以下方式查看:

网络故障排除工具

在本节中,我们将了解一些网络工具/故障排除工具。网络工具对于监控和调试网络问题(如网络连接和网络流量)非常有用。

使用 ethtool 命令

ethtool是一个用于显示和配置以太网卡驱动程序和硬件设置的工具。使用ethtool所做的更改是运行时更改,而非持久性更改。

以下是一些示例,说明ethtool命令的用法:

  • 使用ethtool命令显示以太网接口当前设置,如下所示:
$ ethtool enp0s3
  • 使用ethtool命令显示以太网接口驱动程序设置,如下所示:
$ ethtool -i enp0s3
  • 使用ethtool命令修改以太网接口设置,如下所示:
$ ethtool --change enp0s3 speed 10 duplex half autoneg off
  • 使用ethtool命令,如下所示,闪烁以太网接口端口指示灯 10 秒以进行标识:
$ ethtool --identify enp0s3 10 

使用 ping 命令

ping命令用于验证远程主机的网络连接性。它可以告诉你机器是否连接到网络且在线并响应。它还提供网络丢包和延迟测量的统计信息。

以下是一些示例,说明ping命令的用法:

  • ping命令可以用于识别远程主机的状态(是否存活),如下所示:
$ ping <hostname_or_host_ipaddress>
$ ping 8.8.8.8
  • ping命令可以用于通过指定的接口发送ping请求,如下所示:
$ ping -I eth0 8.8.8.8 
  • ping命令还可以通过向指定的 URL 发送 ping 请求来排查 DNS 问题。如果我们能够使用 IP 地址ping某个 URL,但指定该 URL 的名称时却收不到回复,说明我们的 DNS 服务器设置不正确或无法正常工作。以下是使用 URL 的ping命令示例:
$ ping www.google.com
  • ping命令也可以通过-c选项发送固定数量的数据包,如下所示:
$ ping -c 4 8.8.8.8

在 Windows 系统中,默认情况下,ping命令仅发送四个数据包,而在 Linux 系统中,ping命令会继续发送数据包,直到按下Ctrl + C中止其执行。ICMP ping 不能作为持久的诊断工具,只是众多工具之一。网络诊断依赖于网络中的许多因素。同时,ICMP ping 是最基础和默认的工具,每个系统用户都应了解如何使用它。

使用 tracepath 命令

tracepath命令用于跟踪从源到目的地的路径。tracepath输出中的每一行表示数据包经过的一个路由器(跳跃)。

tracepath命令的示例如下图所示:

使用 traceroute 命令

此命令用于显示或检查数据包到达目的地所经过的网络路径。它在排查网络延迟和错误时非常有用。

默认情况下,traceroute和tracepath命令使用 UDP 包来探测到目的地的路径。如果 IDS 或 IPS 阻止了 UDP 流量,traceroute命令可以选择使用 ICMP(-I)或 TCP(-T)包来检查路径。

以下是一个示例,说明 traceroute 命令的用法:

  • traceroute 命令可用于显示数据包到达网络主机所经过的路由,如下图所示:

使用 mtr 命令

该命令结合了 ping 和 traceroute 的功能。它不断地轮询远程服务器,并获取延迟和性能变化。mtr 命令的使用示例如下所示:

$ mtr www.google.com

执行前述命令后的输出如下所示:

验证 DNS 连接性

CentOS 7 提供了多种工具来验证 DNS 连接性。

使用 nslookup 命令

这是一个网络管理工具,用于查询 DNS 以获取域名或 IP 地址映射,或其他特定的 DNS 记录。它既可以在非交互模式下使用,也可以在命令行界面(CLI)中的交互模式下由用户使用。

以下是一些示例,说明了 nslookup 命令的使用:

  • 使用 nslookup 命令查找域名的 IP 地址,如下所示:
$ nslookup www.centos.org
  • 使用 nslookup 命令查找域名的授权名称服务器,如下所示:www.centos.org/
$ nslookup -type=ns centos.org
  • nslookup 命令可用于对 /etc/resolv.conf 文件中指定的 DNS 服务器执行非授权的 MX 记录查询,如下所示:
$ nslookup -query=mx centos.org
  • nslookup 命令可用于向 DNS 服务器发起授权查询以获取 MX 记录。我们可以指定区域的授权名称服务器作为参数,如下所示:
$ nslookup -query=mx centos.org ns1.centos.org 

使用 host 命令

Host 是最简单的 DNS 查询工具之一。如果不带任何选项使用 host 命令,它会打印出其参数的简要摘要。

host 命令的示例显示在命令行中:

$ host www.centos.org [](http://www.centos.org/) $ host 8.8.8.8

使用 dig 命令

DIG(即 Domain Information Groper 的缩写)是最灵活、最强大的 DNS 查询工具,用于 DNS 故障排除。

以下是一些示例,说明了 dig 命令的使用:

  • 使用 dig 命令查找域名的 IP 地址,如下命令行所示:
$ dig centos.org
  • dig 命令可以通过简短的 DNS 查询,仅返回 IP 地址,如下命令行所示:
$ dig centos.org +short
  • dig 命令可以使用选项关闭额外的信息,仅显示所需的答案,如下命令行所示:
$ dig centos.org MX +noall +answer
$ dig centos.org NS +noall +answer
$ dig centos.org ANY +noall +answer
  • dig 命令可以通过使用 -x 选项执行反向查询(查找指定 IP 地址的主机名),如下命令行所示:
$ dig -x 8.8.8.8 +short

DIG 是一个灵活且多功能的工具。建议参考 dig 工具的手册($ man dig)。

查找本地端口和服务信息

Linux 系统中有多个服务运行在标准的逻辑端口上。著名的端口及其相关服务条目可以在 /etc/services 文件中找到。识别系统中运行的服务状态是至关重要的。有多个命令,如 netstat、ss 等,用于查找本地主机上运行服务的状态。

使用 ss 命令

ss 命令是另一个用于查看套接字统计信息的工具,类似于 netstat 命令。使用 ss 的优点是它能显示比默认存在的其他工具更多的 TCP 和连接状态信息。

这里展示了一个 ss 命令的使用示例:

使用 netstat 命令

如前所述,netstat 命令用于显示所有活动连接和路由表信息。这个命令对于性能监控和故障排除非常有用。

这里展示了一个 netstat 命令的使用示例:

下面是列出常用选项的表格,这些选项与 ss 和 netstat 命令一起使用:

选项 描述
-a 显示所有监听和非监听的套接字
-n 显示数字而非服务名称
-t 显示 TCP 套接字
-u 显示 UDP 套接字
-l 仅显示监听中的套接字
-p 显示套接字的进程 ID 信息

网络工具

本节讨论了各种基于命令行的网页工具,如命令行下载器、命令行网页浏览器等。

图形化和非图形化网页浏览器

网页浏览器是用于通过 万维网 (WWW) 协议检索、传输或处理信息的应用软件。简单来说,它们向网页服务器发送请求,并显示从网页服务器收到的响应。

大多数时候,我们使用图形化网页浏览器,如 Firefox、Google Chrome、Opera 等,然而,有时我们没有图形环境,但仍然需要访问网站。在这些情况下,我们可以使用非图形浏览器,如 Lynx、elinks、W3M 等。

命令行文件下载器 (wget)

wget 命令是 Linux 中最流行的非交互式命令行文件下载工具之一。它可以下载多个文件/目录,并且可以在后台运行。下载的网页可以使用任何图形或非图形浏览器打开。

它的一些常用功能如下:

  • 支持 HTTP、HTTPS 和 FTP 协议,以及通过 HTTP 代理的检索

  • 恢复部分下载

  • 大文件下载

  • 用于镜像网站的递归下载

  • 需要密码的下载

wget 命令的语法如下所示:

$ wget   <url>

这里展示了一个 wget 命令的使用示例:

使用 curl 进行命令行下载和上传

Curl(客户端 URL 库的缩写)是一个非交互式的命令行工具,用于自动化通过网页浏览器完成的 HTTP 任务及其他许多功能。使用 curl,用户可以通过基于 URL 的语法下载多个文件或将文件上传到一个 URL。

一个curl命令使用示例如下:

使用nmcli管理网络

Linux 中有多种网络管理工具,但在 CentOS 7 中,附加的nmcli工具简化并加速了网络设置。nmcli是 NetworkManager 命令行工具的缩写,用于从命令行控制网络管理器工具。nmtui工具曾是系统管理员的最爱,但nmcli节省了大量时间,并且其可用于脚本的功能使其成为 Linux 中最好的网络工具之一。

定义基本术语

以下是与nmcli一起使用的几个基本术语,了解这些术语将有助于我们更好地理解它。

设备或接口

设备是网络接口,如eno1、eno2、enp0s1、eth0等。

连接

在nmcli的上下文中,连接是用于存储设备状态的设置或配置的集合。一个设备可以有多个连接,但一次只能有一个连接处于活动状态。

例如,网络接口的 DHCP 配置可以存储在一个连接中,静态配置可以存储在另一个状态中。这有助于快速切换连接,而无需每次手动更改配置。连接也通常被称为连接配置文件。

使用 nmcli 显示网络信息

我们可以使用nmcli命令显示活动连接列表或所有已保存的连接。

以下是说明如何使用 nmcli 命令显示网络信息的示例:

  • 使用nmcli命令显示所有连接的列表,如下所示:
$ nmcli con show
  • 使用nmcli命令仅显示活动连接,如下所示:
$ nmcli con show --active
  • 使用nmcli命令通过指定连接 ID(NAME)显示连接详情,如下所示:
$ nmcli con show "enp0s3"

显示连接状态的nmcli命令使用示例如下:

  • 使用nmcli命令显示设备(接口)状态为已连接或未连接,如下所示:
$ nmcli dev status
  • 使用nmcli命令显示设备详情,如下所示:
$ nmcli dev show enp0s3

显示设备详情的nmcli命令示例如下:

使用 nmcli 创建网络连接

我们可以使用nmcli命令创建新连接或连接配置文件。在创建连接配置文件时,参数的顺序非常重要。我们可以指定 IP 地址、网关等。连接参数必须包括连接类型、接口名称和连接名称等,以便创建连接配置文件。诸如 DNS 服务器等附加信息,则是在创建连接配置文件后通过修改该配置文件来设置的。

以下是说明如何使用 nmcli 命令创建新连接配置文件的示例:

  • 创建一个名为dhcp的新连接配置文件,该文件将通过 DHCP 连接方式在enp0s8设备上自动连接,如下所示:

  • 创建另一个名为static的新连接配置文件,并通过nmcli命令指定 IP 地址和网关。还需在启动时将自动连接关闭,如下所示:

  • 使用nmcli命令显示系统中存在的连接配置文件,如下所示:

  • 使用nmcli命令将现有设备enp0s8的连接配置文件更改为静态,如下所示:

  • 使用nmcli命令再次将设备enp0s8的连接配置文件切换为dhcp,如下所示:

创建 nmcli 连接配置文件时,我们需要提供的选项取决于所使用的类型。要查看所有可用选项,可以在命令行中输入nmcli con add help。

使用 nmcli 修改网络接口

可以使用nmcli con mod命令修改现有的连接配置文件。可以在此指定其他设置,例如 DNS 服务器。某些属性(如 IP 地址和网关)在创建连接配置文件时使用的名称与修改后使用的名称不同。

nmcli con mod命令后跟的是一组键/值对参数。nmcli con show <connection_profile_name>命令用于列出当前连接的键值。

当将 DHCP 连接配置文件修改为静态时,ipv4.method属性键应设置为manual:

创建时的属性名称 修改时的属性名称
ip4 ipv4
gw4 gwv4

以下是说明如何使用 nmcli con mod 命令修改网络接口设置的示例:

  • 在命令行中关闭连接配置文件的自动连接,如下所示:
$ nmcli con mod "static" connection.autoconnect no
  • 使用nmcli con mod命令指定 DNS 服务器,如下所示:
$ nmcli con mod "static" ipv4.dns "1.1.1.1"
  • 我们可以通过在参数前添加+或-符号,进一步向某个键添加更多值。我们还可以使用nmcli con mod命令添加另一个 DNS 服务器,如下所示:
$ nmcli con mod "static" +ipv4.dns "8.8.8.8"
  • 我们可以如下面所示修改连接配置文件的静态 IP 地址和网关:
$ nmcli con mod  "static"  ipv4.address  "50.50.50.50/24" ipv4.gateway  "50.50.50.254"
  • 我们可以在现有配置文件中为同一接口分配一个不带网关的二级 IP 地址,如下所示:
$ nmcli con mod "static" +ipv4.addresses "70.70.70.100/16"
  • 要激活更改,需要使用nmcli con命令激活连接配置文件,如下所示:
$ nmcli con up "static"
  • 使用nmcli del命令删除连接配置文件,如下所示:
$ nmcli del "static"
  • 使用nmcli命令禁用所有受管理接口,如下所示:
$ nmcli net off
  • 通过暂时断开设备来关闭接口,如下所示:
$ nmcli dev dis enp0s8
  • 通过连接设备来启动接口,如下所示:
$ nmcli dev con enp0s8

编辑网络配置文件

在前一部分中,我们了解了如何使用nmcli配置静态和动态 IP 地址。除了 NetworkManager 的命令行接口和 GUI 接口,我们还可以通过修改网络接口配置文件手动配置网络。在任何时候,我们可以通过手动配置网络接口文件或使用 NetworkManager 来配置网络,但不能同时使用两者。网络接口文件(脚本)的存储位置在不同的 Linux 发行版中有所不同。在 CentOS 7 中,网络接口配置文件存储在/etc/sysconfig/network-scripts/文件夹中,并且其命名规则以ifcfg-<device_name>开头。

配置静态和动态模式下的网络选项

我们可以通过修改网络接口配置文件以手动配置静态 IP 地址或 DHCP IP 地址模式。

以下是手动配置 CentOS 7 网络的示例:

  • 动态(dhcp)配置的ifcfg文件如下所示:

  • ifcfg文件的静态配置如下所示:

如果要在静态配置中分配多个 IP 地址、前缀或网关,则在其后加上一个数字。如果要分配多个 DNS 服务器,它们将按照查找顺序编号,如下所示:

在对配置文件进行所需更改后,需要重新启动网络服务,或者可以运行nmcli con reload命令。这样会使 NetworkManager 重新读取配置文件并应用更改。在重新加载nmcli配置时,接口需要先上升再下降一次,才能使更改生效,如下所示:

$ nmcli con reload
$ nmcli con down "static"
$ nmcli con up "static"

配置主机名和名称解析

主机名和 DNS 服务器在网络中扮演着重要角色,因为计算机可以通过 IP 地址或主机名在网络中访问。DNS 服务器负责将 IP 地址转换为域名,也负责将域名转换为 IP 地址。这个转换过程也被称为名称解析或DNS 解析。

自 CentOS 7 起,静态主机名被存储在一个新的文件中,/etc/hostname。在早期版本中,它存储在/etc/sysconfig/network文件中。现在,新增了一个名为hostnamectl的命令,用于查看和修改机器的主机名。

显示和修改主机名

hostname命令用于查看主机名或在运行时临时修改主机名。而hostnamectl命令用于通过命令行永久修改主机名。

以下是说明hostname命令用法的示例:

  • 使用hostname命令查看 CentOS 7 的完全限定主机名,如下所示:

  • 使用hostname命令临时修改完全限定的主机名,如下所示:

以下是说明hostnamectl命令用法的示例:

  • 使用hostnamectl命令查看已修改的主机名变化,如下截图所示:

  • 使用hostnamectl命令可以永久修改主机名,如下截图所示:

修改名称服务器(DNS 服务器)

域名与 IP 地址之间的查询顺序在本章前面已讨论。DNS 服务器(名称服务器)的信息存储在/etc/resolv.conf文件中。nameserver指令后跟名称服务器的 IP 地址,用于查询 IP 查找。如果一个名称服务器宕机,最多可以在此文件中指定三个nameserver指令以提供备份。

/etc/resolv.conf中的 DNS 服务器条目由 NetworkManager 管理。如果 NetworkManager 正在运行,我们应该使用nmcli或图形界面 NetworkManager 来添加或修改 DNS 服务器。

以下示例用于解释如何查看或修改系统的名称服务器:

  • 显示名称服务器详细信息,如下所示:

  • 我们可以通过为特定连接配置文件添加 DNS 服务器来使用nmcli修改名称服务器条目,如下所示:
$ nmcli con mod <connection_profile> ipv4.dn <ip_of_dns_server>
$ nmcli con mod  "static"  ipv4.dns "8.8.8.8"

如果 NetworkManager 正在运行,那么对/etc/resolv.conf文件的手动修改将被 NetworkManager 覆盖。因此,要手动修改并保留/etc/resolv.conf文件中的条目,我们应该先关闭 NetworkManager,然后再进行修改,如下所示:

$ vi /etc/resolv.coonf 
search mydomain.com
nameserver 8.8.8.8
nameserver 1.1.1.1

使用 SSH 访问远程登录

SSH 是一个 OpenSSH 客户端程序,用于安全地登录到远程计算机进行远程管理。它为两台主机之间提供经过身份验证的加密通信通道,适用于不可信的网络。

理解 OpenSSH

SSH 组件可以分为两个部分。第一个是 OpenSSH 服务器(sshd 服务),它安装并运行在远程服务器上,接受来自 OpenSSH 客户端的连接。默认情况下,它使用 TCP 协议在 22 端口上运行,防火墙应该允许 OpenSSH 客户端连接。

第二个组件是 SSH 客户端,应该安装在任何客户端系统上(Linux、Windows 或 macOS),从这些系统中你可以连接到运行 OpenSSH 服务器的系统进行远程管理。

因此,SSH 协议通过客户端-服务器架构促进了两个系统之间的安全通信。SSH 完全加密用户登录会话,从而使入侵者难以嗅探任何未加密的密码,并消除了中间人攻击(MITM)的网络风险。SSH 使用私钥-公钥方案进行认证,进一步消除了网络上的冒充攻击。

远程通过 SSH 执行命令

以下是一些示例,说明了 ssh 命令的基本用法:

  • ssh 命令可以使用当前登录的客户端用户名登录远程系统,连接到 SSH 服务器,如命令行和下图所示:
$ ssh <hostname_or_ip_address> 

  • ssh 命令可以通过指定用户名和主机名/IP 地址以另一个用户身份执行,如下所示:
$ ssh <username>@<hostname_or_ip_address>
or 
$ ssh -l <username> <hostname>

以下是以不同用户身份执行 ssh 命令的示例:

  • 你可以通过 ssh 在远程系统上执行命令,如下所示:
$ ssh <username>@<hostname_or_ip_address> <command_name>

通过 ssh 在远程系统上执行命令的示例,如下图所示:

基于密钥的 SSH 认证

SSH 通信通过公钥加密技术保障安全。当用户第一次使用 SSH-client 连接到 SSH-server 时,SSH 程序会将 SSH-server 公钥存储在用户的主目录下的一个名为~/.ssh/的隐藏文件夹中的 known_hosts 文件里,如下图所示:

下图显示了远程主机的公钥指纹示例,保存在客户端的已知主机文件中:

现在,每当 ssh-client 连接到服务器时,它会将服务器发送的公钥与存储在~/.ssh/known_hosts文件中的服务器公钥进行比较。如果公钥不匹配,客户端会认为网络流量可能被劫持,或者连接的服务器不一样,因此 SSH-client 会断开连接,如下所示:

服务器可能会因为某些合法原因被重新格式化,或服务器密钥被替换。在这种情况下,用户需要通过删除旧的密钥来更新他们的~/.ssh/known_hosts文件,以便重新登录服务器。

配置 ssh-keygen 实现无密码认证

SSH 服务器有多种方式来验证连接到它的客户端。最常见的方式是基于密码的身份验证,因为它是最简单的方法,但它的安全性较差。密码通过安全机制进行交换,然而由于易于使用,密码通常不够复杂或长。因此,攻击者可以通过暴力破解或字典攻击来破解密码。在这种情况下,SSH 密钥可以为客户端提供一种安全可靠的认证方式。

SSH 服务器使用公钥密码学方案进行用户认证。在这种方案中,会生成一对密钥,即公钥和私钥,用于身份验证。顾名思义,私钥由客户端保密,因为私钥泄露可能导致未经额外身份验证就能登录到服务器。

客户端的秘密私钥对应的公钥不会被保密,而是被复制到用户登录的系统中。私钥用于解密使用客户端关联的公钥加密的消息。通过使用密钥对,我们还可以实现无密码认证。

客户端的受信任公钥存储在一个名为authorized_keys的特殊文件中,该文件位于用户帐户的home目录中,用于登录,如下图所示:

当客户端尝试使用密钥进行 SSH 服务器身份验证时,服务器会使用存储在服务器上的客户端公钥发起挑战。成功使用客户端私钥解密挑战后,用户即可访问服务器的 shell。

除了基于密码和基于密钥的认证方式外,SSH 还支持 Kerberos 和 gssapi 等认证方式。

创建 SSH 密钥对

在此步骤中,客户端使用一个特殊的工具ssh-keygen来生成用于与服务器进行身份验证的 SSH 密钥对。该工具与 OpenSSH 一起捆绑,默认情况下它创建一个 2048 位的 RSA 密钥对。它支持 RSA 和 DSA 两种加密算法,每种算法支持不同长度的密钥。建议使用 4096 位的密钥长度,以便在两台机器之间建立安全连接。下图展示了如何创建一个 2048 位的 RSA 密钥对:

系统会提示你选择生成密钥的存储位置。默认情况下,密钥存储在用户的主目录下的~/.ssh目录中,私钥命名为id_rsa,公钥命名为id_rsa.pub。私钥的权限为 600,公钥的权限为 644。

然后,它会提示你为密钥输入一个可选的密码短语,该密码短语用于解密本地计算机(客户端)上的密钥。因此,暴力破解或字典攻击无法对这个密码短语进行攻击。密码短语还提供了额外的安全性,以防系统被攻破。例如,当 SSH 密钥已在被攻破的系统中交换时,它可以防止攻击者登录到其他服务器。下图显示了用于身份验证的 RSA 密钥对公钥:

现在,为了启用基于密钥的身份验证,需要将客户端的公钥复制到运行 SSH 服务器的目标系统。

以下示例演示了如何使用ssh-copy-id命令将公钥复制到远程计算机:

  • 有一个工具,ssh-copy-id,它也包含在 OpenSSH 中,可以用来将密钥复制到远程系统。默认情况下,它会将~/.ssh/id_rsa.pub文件复制到远程系统,如下所示:

ssh-copy-id命令的一般语法如下:

$ ssh-copy-id     username@remotehost
  • 以下图示展示了如何在远程主机上进行 SSH 登录而不需要输入密码:

  • 另一种将公钥复制到远程主机authorized_keys文件中的方法,如下所示:
$ cat ~/.ssh/id_rsa.pub | ssh student@192.168.56.100 "cat >> ~/.ssh/authorized_keys"

现在,通过在提示时输入密码短语来 SSH 登录远程主机(仅在创建密钥时给定密码短语时需要)。

配置和保护 SSH 登录

可以通过修改远程主机上的 OpenSSH 服务器配置文件/etc/ssh/sshd_config,启用额外的安全措施。以下是一些可以采取的措施来保护 SSH 登录:

  1. 现在,由于我们在前一节中已配置了基于 SSH 密钥的身份验证,因此可以禁用密码身份验证来保护 SSH 登录。编辑远程主机上运行 SSH 服务器的 SSH 守护进程配置文件,并将PasswordAuthentication指令的值设置为no,如下所示:
$ vi /etc/ssh/sshd_config
PasswordAuthentication no
  1. 禁止通过 SSH 直接以 root 用户身份登录,因为 root 用户具有无限制的权限,并且默认情况下每个 Linux 系统上都有 root 用户。为了通过 SSH 保护 root 用户账户,我们可以在配置文件中做如下更改:

    • 注释掉带有指令PermitRootLogin的行,如下所示:
 #PermitRootLogin yes
    • 将指令PermitRootLogin的值设置为no,如下所示:
PermitRootLogin no
    • 通过将指令PermitRootLogin的值设置为without-password,仅允许使用密钥进行 root 账户的 SSH 登录,如下所示:
PermitRootLogin without-password
  1. 在修改完 SSH 服务器配置文件/etc/ssh/sshd_config后,重新启动sshd服务,以使所做的更改生效,如下所示:
$ systemctl restart sshd

在 Linux 中传输文件

我们已经看过如何使用 SSH 保护客户端与远程主机服务器之间的通信。在本节中,我们将安全地传输两个连接机器之间的文件。CentOS 7 提供了两个常用的工具,scp和rsync,用于在连接的机器之间进行安全的数据传输。

使用 SCP 进行安全文件传输

scp命令用于安全地从本地系统传输文件到远程主机,或者从远程主机传输文件到本地系统。它使用 SSH 服务器进行安全(加密)数据传输和身份验证。

ssh、scp和sftp被打包成ssh软件包,并在安装ssh时自动安装。

从本地到远程文件系统的文件传输

从本地系统传输文件到远程文件系统的语法如下:

$ scp    <local_filenames>    <username>@<host>:<remote_host_directory>

执行前面的命令时,系统会提示输入远程用户密码。输入正确的密码后,文件传输将开始,如下图所示:

从远程到本地文件系统的文件传输

从远程系统传输文件到本地文件系统的语法如下:

$ scp    <username>@<host>:<remote_host_file>    <local_path>

执行前面的命令时,系统会提示输入远程用户密码。输入正确的密码后,文件传输将开始,如下所示:

使用 rsync 同步文件

Rsync 是另一个用于快速、安全地从一个系统复制文件到另一个系统的工具。它使用 SSH 连接进行数据传输,并与 SCP 不同,因为它仅复制现有文件中的差异。Rsync 比 SCP 更快,因为它仅复制文件之间的差异,而 SCP 则会复制所有内容。

下表列出了与rsync命令一起使用的重要选项及其说明,用于同步文件和文件夹:

选项 说明
-a 存档模式(包括递归、同步符号链接、保留权限、保留组所有权、时间戳、文件所有权,以及同步设备文件)。它相当于以下选项:-rlptgoD
-v 同步时在输出中增加详细信息。
-r 递归同步整个目录树。
-n 执行干跑操作,不做任何更改。
--remove-source-files 同步后的文件将从发送系统中删除。
-z 在从源到目标的传输过程中压缩文件数据。
-X 从源到目标同步 SELinux 上下文。
-A 同步文件的 ACL。

在本地从一个文件夹到另一个文件夹同步数据进行备份

用于从一个文件夹备份到另一个文件夹的本地同步语法如下:

$ rsync    -<options>    <source_directory>    <destination_directory>

下面是一个rsync命令使用示例,用于同步本地文件:

从本地到远程主机文件系统同步数据

本地到远程主机文件系统同步的语法如下:

$ rsync   -<options>   <source_directory>   <username>@<host>:<remote_host_directory>

执行上述命令时,系统会提示输入远程用户密码。输入正确密码后,文件同步将开始,如下所示:

从远程主机同步数据到本地文件系统

远程主机到本地文件系统同步的语法如下:

$ rsync     -<options>      <username>@<host>:<remote_host_directory>     <local_directory>

执行上述命令时,系统会提示输入远程用户密码。输入正确密码后,文件同步将开始,如下所示:

总结

在本章中,我们首先学习了基本的网络概念,如 IP 地址、DNS、网关等。接着,我们介绍了 CentOS 7 中常用的基本网络命令。然后,我们了解了如何使用 nmcli(NetworkManager 命令行界面)管理网络接口,手动编辑网络配置文件进行配置,以及如何修改主机名、DNS 服务器参数等。随后,我们学习了如何使用 SSH 客户端和密码以及公钥认证来安全地连接远程主机。最后,我们学习了如何使用命令行安全地传输和同步文件,以便从一台主机备份到另一台主机。

在下一章中,我们将学习如何保持 CentOS 7 及其安装的应用程序始终保持最新。我们还将学习如何通过命令行安装或删除不需要的应用程序。

第八章:软件包管理

为了保持系统最新,并根据需要安装或删除应用程序,Linux 支持多种方法。一种方法是使用应用程序的源代码进行编译并安装到机器上。另一种方法是使用预构建的程序或一组程序,称为包,这些程序已经准备好在特定的发行版上安装。

在本章中,你将学习如何使用 RPM 和 YUM 工具管理这些预构建的软件包。你还将学习如何在 CentOS 7 中添加或删除官方和第三方仓库。

在本章中,我们将涵盖以下主题:

  • 使用 RPM 管理应用程序

  • 使用 YUM 管理应用程序

  • 管理官方和第三方仓库

  • 创建自定义仓库

使用 RPM 管理应用程序

RPM(即Red Hat 软件包管理器)是由 Red Hat 为基于 RPM 的系统(如 RHEL、CentOS 和 Fedora)开发的开源包管理工具。使用 RPM 工具,用户可以安装、删除、更新、查询和验证以.rpm格式构建的应用程序包。你可以从包含.rpm格式应用程序包的仓库下载.rpm包。

一个 RPM 包可能需要或不需要任何资源前提。如果一个 RPM 包需要某些资源,比如共享库或其他包必须在安装该 RPM 包之前存在于系统中,那么这些资源被称为该包的依赖项。像 YUM 这样的包管理工具会在安装包时自动解决依赖关系,而 RPM 工具则没有此功能。使用 RPM 工具,你可以查找包的依赖项,但 RPM 无法自动安装它们。RPM 工具也被称为低级包管理工具。

RPM 的结构

每个 RPM 包文件的命名遵循一个标准,如下所示:

name-version-release.architecture.rpm

用于 RPM 包的命名约定如下面的图示所示:

下表描述了用于命名 RPM 包的各个字段及其描述:

字段 描述
名称 它由描述应用程序内容的字符串组成。
版本 它是应用程序的版本号。
发布 它是由打包者设置的包的发布编号。

| 架构 | 它描述了包的架构。它说明包是为哪种架构构建的:32 位、64 位,或两者兼有:

  • i386:32 位

  • x86_64:64 位

  • noarch:与任何架构无关,可以在 32 位和 64 位系统上使用

|

使用 RPM 包安装应用程序具有管理的额外优势(跟踪包文件、更新包、删除包)。几乎所有 CentOS 提供的软件都是以 RPM 包的形式提供的。

RPM 包主要由三个部分组成:元数据、文件和脚本。元数据包含包名、版本、发布、构建者、日期、依赖关系等信息。文件部分包含要安装的包中包含的文件档案。RPM 包内的脚本文件会在安装、移除或更新包时执行。

更新应用程序时会发生什么

当应用程序更新时,通常,旧版本的包会从系统中移除。现有的配置文件通常会被保留,但是否保留、覆盖或以不同的名称写入新的配置文件则是在创建包时决定的。

在典型情况下,每次只安装一个版本的应用程序。然而,在某些情况下,可能会存在同一应用程序的多个版本,比如内核包或在多架构环境中,同一包会为不同架构(32 位和 64 位)安装。内核包设计时考虑到可以保留多个版本。如果新的内核安装失败,旧版本的内核始终可以作为备用。请始终记住,内核包从不通过 RPM 工具的更新选项进行更新,它总是安装而不是更新。

使用 RPM 查询选项与 RPM 包一起使用

有几个选项可以与查询选项一起使用。一些常用的选项如下:

  • 列出系统中安装的所有包:
$ rpm -qa
  • 通过将上一命令的输出传递给 grep 命令来查找系统中安装的特定包,如下所示:

  • 如下所示,识别安装了某个文件的包:

  • 显示 RPM 包安装的文件列表,如下所示:

  • 显示最近安装的 RPM 包,如下所示:

  • 显示已安装包的信息,如下所示:

  • 显示包安装的文件文档,如下所示:

  • 显示包安装的文档,名称如下所示:

  • 显示包安装的配置文件,如下所示:

  • 显示特定包的变更信息列表,如下所示:

验证 RPM 包签名

RPM 包通常由打包它们的组织、社区或个人使用 GPG 私钥签名。在我们系统上安装包之前,我们应始终使用其公共 GPG 密钥验证包的签名,以确认其完整性。以下命令用于检查 RPM 包的签名:

$ rpm --checksig <packagename.rpm>

使用 RPM 安装包

要安装包,使用-i选项。通常与-v和-h选项一起使用,以便在安装过程中显示详细信息并使用哈希符号显示安装进度,如下所示:

使用此方法的缺点是 RPM 无法自动解析依赖关系,因此如果在安装包时遇到任何未满足的依赖关系,它将中途退出安装。

我们还可以使用 RPM 强制安装包,通过在安装过程中使用--nodeps选项禁用依赖检查。这个方法不推荐使用,因为程序可能会在没有解析依赖关系的情况下失败。

使用 RPM 工具强制安装包的示例如下所示:

使用 rpm 删除包

我们可以通过指定包名和-e选项来删除一个包,如下所示:

我们也可以在不进行依赖检查的情况下删除一个包。这将强制从系统中删除包,任何依赖该包的应用程序可能无法运行。以下图示显示了如何在不检查依赖关系的情况下删除包:

使用 RPM 升级包

大多数情况下,已安装的包会通过像 YUM 这样的高级包管理器自动升级。然而,如果包无法通过中央仓库升级,可以从互联网下载并手动升级,如下所示:

$ rpm -U <file.rpm> 

我们可以使用前面的命令或下面的命令手动升级一个包:

$ rpm -Uvh <file.rpm>

下面是使用rpm命令升级包的示例:

使用 RPM 验证包

如下所示,验证包的已安装文件与 RPM 文件中的文件是否一致:

导入 RPM GPG 密钥

在安装前验证包的完整性时,必须将仓库或包作者的公共 GPG 密钥导入到系统中。以下截图显示了导入 CentOS 7 GPG 密钥的命令:

显示系统上所有导入的 RPM 仓库的 GPG 密钥,如下图所示:

使用 YUM 管理应用程序

YUM(Yellowdog Updater Modified的缩写)是由 Red Hat 公司为基于 RPM 的系统开发的开源工具。它是一个高级包管理工具,用于在系统或网络仓库中轻松安装、删除、更新或搜索软件包。它允许我们使用 CentOS 基础和第三方仓库,这些仓库可以托管在远程或本地服务器上,在解决依赖关系后自动安装单个包或一组包。

在未来的版本中,YUM 将被 DNF 替代(其命令集兼容)。YUM 已在 Fedora 中被 DNF(改良版 YUM)替代,成为主要的包管理工具。

理解 YUM 包管理器

YUM 的主配置文件是/etc/yum.conf,存储仓库配置文件的主目录是/etc/yum.repos.d/。仓库配置文件有特定的语法,且应以.repo扩展名结尾,存放在/etc/yum.repos.d/目录下。

仓库配置文件包含仓库的 URL、repo id、repo name、使用 GPG 检查软件包签名的说明以及启用或禁用仓库的选项。

使用 YUM 命令行

在本节中,我们将学习如何在 Linux 命令行中使用 YUM 进行包管理。

使用 yum 查找应用程序

我们可以通过多种方式使用 YUM 搜索包名。带有关键字(包名)的搜索选项将列出包名本身以及包的摘要字段中包含指定关键字的包。以下示例用于说明yum search命令的工作方式:

  • 仅通过包名使用yum search命令查找包,如下所示:
$ yum search <package_name>

下面是一个使用 yum search 命令查找名为whois的包的示例:

  • 查找包时,如果搜索字符串出现在名称、摘要和描述字段中,则可以找到包,如下所示:

  • 使用yum whatprovides命令根据包描述搜索包,如下所示:
$ yum whatprovides "*/package_name"

下面是一个使用yum whatprovides命令查找包名lynx的示例:

  • 使用yum provides命令识别在系统中安装了某个文件(绝对路径名)的包,如下所示:

使用 YUM 安装应用程序

我们可以使用 YUM 工具安装新包。YUM 工具将解析包的所有依赖关系,并在安装前提示确认。

以下是一些示例,用于说明使用 yum 命令安装包的方法:

  • 使用以下命令通过 YUM 安装应用程序:
$ yum install firefox
  • 使用-y选项安装应用程序而不提示确认:
$ yum -y install firefox
  • 安装一个不验证其签名的包:
$ yum install firefox --nogpgcheck
  • 从本地目录安装已下载的 RPM 文件。它会自动从配置的仓库下载包的依赖项:
$ yum localinstall <path_to_rpm_file>

yum localinstall命令的示例如下所示:

使用 YUM 显示软件包及其信息

以下是使用yum命令显示软件包详细信息的示例:

  • yum info命令的用法如这里所示:

  • 使用yum list命令显示已安装软件包列表,如命令行中所示:
$ yum list installed
  • 使用yum list命令按名称显示已安装和可用的软件包信息,如下图所示:

  • yum list命令也可以用来显示来自 YUM 数据库的所有可用软件包,如命令行中所示:
$ yum list

使用 yum 删除应用程序

以下是使用yum命令删除应用程序包的示例:

  • yum命令可用于删除一个软件包及其所有依赖项,如命令行中所示:
$ yum remove firefox
  • yum命令还可以与-y选项一起使用,以在没有提示确认的情况下删除应用程序,如命令行中所示:
$ yum -y remove firefox

使用 yum 更新应用程序和系统

我们可以通过执行命令行来查看系统中已安装的软件包是否有更新,如下所示:

$ yum check-update

我们还可以使用yum命令将已安装的应用程序及其依赖项更新到最新的稳定版本。在此过程中,YUM 会保留现有的配置文件,除非必须更新配置文件以便在更新版本的应用程序上工作,如命令行中所示:

$ yum update httpd

我们可以通过不指定任何应用程序名称给yum update命令,从而在一条命令中同时更新系统和已安装的应用程序,如命令行中所示:

$ yum update

在更新系统或应用程序时,除了内核以外,所有应用程序会立即在运行时更新。最新的内核版本仅在重新启动系统后生效。我们可以使用uname -r命令查看当前运行的内核版本。

使用 YUM 管理应用程序组

在 CentOS 7 中,执行相同功能的相关软件包被分组在同一类别下。我们还可以通过安装特定的包含相关软件包的组来代替逐一安装,如下所示的示例:

  1. 使用yum grouplist命令显示所有软件包组,如下所示:
$ yum grouplist
  1. 使用yum groupinstall命令安装相关软件包的特定包组,如下所示:
$ yum groupinstall "Development Tools"
  1. 使用yum groupupdate命令更新现有安装的软件包组中的软件包,如下所示:
$ yum groupupdate "Administration Tools"
  1. 我们还可以使用yum groupremove命令从系统中移除已安装的软件包组,如下所示:
$ yum groupremove "Development Tools"

我们可以使用yum groupinfo命令显示系统中已安装或未安装的强制性、默认和可选软件包的信息。此命令的输出显示该组中的软件包列表,每个软件包名前都会显示一个符号。下表列出了符号及其对应的含义:

符号 含义
= 软件包作为该组的一部分被安装,并且目前已安装在系统上。
+ 系统上未安装该软件包。如果安装或更新该组,软件包将会被安装。
- 系统上未安装该软件包,如果安装或更新该组,软件包将不会被安装。
无符号 软件包已安装在系统上,但不是通过该组安装的。

yum groupinfo命令的一个示例,用于查找通过组安装的软件包的信息,如命令行所示:

$ yum groupinfo "System Administration Tools"

使用 YUM 历史记录

YUM 会在日志文件/var/log/yum.log中记录所有过去的安装和移除事务。以下截图显示了如何查看存储在日志文件中的 yum 事务记录:

我们可以使用yum命令显示已安装和已移除的软件包的历史记录,如下所示:

我们可以使用yum history undo命令撤销之前的事务,如下所示:

使用 YUM 管理应用程序仓库

要使用 YUM 管理应用程序仓库,请执行以下操作:

  • 使用yum repolist命令仅显示系统中已启用的仓库,如下所示:
$ yum repolist
  • 使用yum repolist all命令显示系统中所有可用(启用或禁用)的仓库,如下所示:
$ yum repolist all
  • 我们可以通过仅在运行时启用某个仓库来安装来自特定仓库的软件包。它用于在一个软件包存在于多个仓库时,从特定仓库安装该软件包,如命令行所示:
$ yum  --enablerepo=epel install httpd
  • 我们可以使用yum-config-manager工具永久启用或禁用一个仓库。它会在/etc/yum.repos.d/目录下的文件中进行必要的更改,如命令行所示:
$ yum-config-manager  --enable <repo id>

yum-config-manager工具还可以用于在/etc/yum.repos.d目录下创建客户端仓库配置文件,如下所示:

$ yum-config-manager       \                                        --addrepo=http://repo.example.com/7/x86_64/

处理其他杂项 yum 选项

YUM 工具还提供了一个交互式 Shell,通过 yum shell 命令一次性执行多个任务。要退出 YUM Shell,请输入 exit 或 quit,或按 Ctrl + D。以下截图中的示例说明了 yum shell 命令的用法:

YUM 会将所有启用的仓库的缓存包和其他数据存储在 /var/cache/yum 目录中。在这里,YUM 会为每个仓库创建一个子目录。我们可以通过执行以下命令随时清理或清空缓存目录,以节省空间:

$ yum clean all

我们可以使用以下命令显示 YUM 的使用信息:

$ yum help

管理官方和第三方仓库

有时,所需的软件在 CentOS 7 的基础(官方)仓库中不可用。在这种情况下,CentOS 7 和其他 Linux 社区已贡献了多个第三方仓库,可以用于安装官方仓库中没有的各种应用程序。本节将讨论适用于 CentOS 7 的各种流行第三方仓库。

CentOS 7 的官方仓库

默认情况下,CentOS 7 提供基础仓库、更新仓库和附加仓库。这些仓库由 CentOS 社区管理,足以满足大多数日常操作需求。

第三方仓库

这些是没有由官方 CentOS 社区管理的仓库。有时,我们需要将它们添加到 YUM 仓库数据库中,以便下载和安装在 CentOS 官方仓库中没有的软件。然而,如果添加这些仓库,应该单独管理它们,以避免它们带来的任何意外或冲突更新。

以下是一些特定仓库的列表,这些仓库包含在 CentOS 基础仓库或更新仓库中没有的额外 CentOS 包:

  • 企业 Linux 扩展包(EPEL)仓库:该仓库由 Fedora 社区维护,是可以添加到系统中的最受信任的第三方仓库之一。我们可以使用以下命令将此仓库添加到系统中:
$ yum install epel-release -y 
  • 社区企业 Linux 仓库(ELRepo):这是一个企业 Linux 仓库,提供与硬件相关的 RPM 包。它包括文件系统驱动程序、图形、声音、摄像头、视频和网络驱动程序,以及最新的内核包。我们可以使用以下命令将此仓库添加到系统中:

  • Nux-desktop 仓库:该仓库提供面向企业版 Linux 的桌面和多媒体相关软件包。一些流行的多媒体软件,如 VLC 媒体播放器、mplayer 等,都可以通过这个仓库安装。此仓库中的一些软件包有一些依赖项,这些依赖项可以通过 EPEL 仓库解决。同时,强烈建议不要与 RPMForge 或 ATRPMS 仓库一起使用此仓库,因为它可能会导致软件包和依赖项之间的冲突。此外,RPMForge 已经是一个废弃的项目,不再维护。我们可以通过以下命令将 Nux-desktop 仓库添加到系统中:
$ yum install epel-release 
$ rpm -Uvh \
http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
  • Remi 仓库:这是一个第三方仓库,主要以提供最新版本的 PHP 堆栈、MySQL 及相关软件而闻名,通常用于企业版 Linux。安装之前,它还需要先在 CentOS 上安装 EPEL 仓库。我们可以通过以下命令将 Remi 仓库添加到系统中:
$ yum install epel-release
$ rpm -Uvh https://rpms.remirepo.net/enterprise/remi-release-7.rpm

默认情况下,remi 仓库在安装时未启用。要使用此仓库安装软件包,我们需要先启用它。

  • RPM Fusion 仓库:这个第三方仓库提供一些 Fedora 项目或 Red Hat 不希望与企业版 Linux 共享的免费和非免费附加包。我们可以通过以下命令将此仓库添加到系统中:
$ rpm -Uvh https://download1.rpmfusion.org/free/el/rpmfusion-free-release-7.noarch.rpm

有许多第三方仓库可供选择,其中一些不再维护,而一些则存在包冲突。有关仓库的更多信息,例如哪些仓库应该避免使用,哪些仓库推荐使用,你可以访问 CentOS 的以下 Wiki 页面:

wiki.centos.org/AdditionalResources/Repositories

创建自定义仓库

创建一个 YUM 仓库是通过局域网在多台系统上安装软件或安全更新的最简单和最好的方法之一。我们可以从互联网仓库或 DVD 下载所有的软件包,并将它们托管在本地服务器上,该服务器将被称为 YUM 服务器。局域网中的其他 Linux 机器可以配置为从本地 YUM 服务器下载所需的软件包,这些机器将被称为 YUM 客户端。这样可以节省互联网带宽,提供离线安装软件包给客户端,并加速更新过程。

在本节中,我们将创建一个自定义的 CentOS 7 DVD 包仓库,并通过 FTP 服务器将该仓库共享给客户端,步骤如下:

  1. 挂载包含软件包的介质。在本例中,它将是 CentOS 7 DVD,如下所示:

  1. 从挂载的 DVD 中安装 FTP 服务器包 vsftpd,如下所示:

  1. 现在,启用服务以便在启动时自动启动 vsftpd 并启动该服务,如下所示:

  1. 安装createrepo软件包以创建本地仓库数据库。如果系统连接了互联网,我们可以使用 YUM 来安装createrepo软件包,如命令行所示:
$ yum install createrepo -y

如果没有互联网连接,可以使用 RPM 包管理器安装软件包,如下所示:

我们遇到前面的错误是因为在系统中未安装createrepo软件包的依赖项。因此,我们满足了createrepo软件包的依赖关系。首先,按以下顺序安装以下软件包:

  1. 将软件包存储在ftp文件夹中以构建本地仓库,如下所示:

  1. 根据vsftpd服务器文件恢复从 DVD 复制的软件包的 SELinux 标签,如下所示:

  1. 在/etc/yum.repos.d/目录下创建一个以.repo扩展名结尾的 YUM 服务器配置文件,如命令行所示:
$ vim /etc/yum.repos.d/localserver.repo

localserver.repo文件的内容如下所示:

  1. 启用本地 YUM 服务器仓库并使用yum命令清理 YUM 缓存,如下所示:
$ yum clean all

在清理 YUM 数据库的先前缓存后,使用如下命令从头开始构建仓库的 YUM 数据库:

你可以使用其他应用程序,如 Web 服务器或 NFS 服务器,来共享 YUM 服务器(提供软件包的系统)到 YUM 客户端(下载软件包的系统)。我们还需要在防火墙中打开相应的应用程序端口,以允许 YUM 客户端从 YUM 服务器下载软件包。

总结

在本章中,我们首先学习了如何保持系统和应用程序软件的更新。我们了解了如何使用 RPM 和 YUM 等软件包管理工具来安装、移除或更新应用程序包。我们还查看了 CentOS 7 的不同第三方仓库。最后,我们通过创建自定义仓库并使其对客户端可用来结束本章。保持系统和应用程序的更新至关重要,可以确保它们没有任何漏洞,有助于保护信息并使系统免受恶意软件和黑客的攻击。

在下一章中,我们将学习一些 CentOS 7 的基本工具。我们将看到系统日志如何工作以及如何管理系统服务。接着,我们将了解防火墙和 SELinux 在强化系统安全方面的功能。

第九章:必备高级工具概览

在本章中,我们将学习一些与系统相关的高级和基本概念,如日志记录、控制系统服务、防火墙和安全增强 Linux(SELinux)。日志记录在调试和故障排除系统应用程序中起着关键作用。深入理解日志记录将使你的日常操作更加轻松,也将帮助你深入了解应用程序的功能。

在本章的最后,我们将学习 CentOS 7 中不同的日志机制,如 journald 和 rsyslog。到目前为止,你已经看到了如何安装、更新和删除应用程序。现在,我们将学习如何使用 systemd 和 systemctl 工具控制这些应用程序和系统服务。最后,我们将理解如何使用 firewalld 和 SELinux 来保护正在运行的服务并加强系统的安全性。

我们将涵盖以下内容:

  • 理解系统日志

  • 与 rsyslogd 和 journald 一起工作

  • 理解系统和服务的控制

  • 与 systemd 和 systemctl 一起工作

  • 理解 SELinux 概念

  • 与 SELinux 一起工作

  • 理解 CentOS 7 中的防火墙概念

  • 与 firewalld 一起工作

理解系统日志

大多数应用程序和内核将它们的事件信息写入保存在不同位置的日志文件中。这有助于跟踪系统上发生的活动,并且也是系统审计的重要组成部分。日志文件的监控有助于发现系统中的任何异常活动。日志记录还有助于排除应用程序问题。根据惯例,Linux 使用/var/log/目录来存储系统中的日志。

从 CentOS 7 开始,系统中存在两种日志服务:

  • Rsyslog 服务

  • Systemd-journald 服务

在配置日志服务之前,应该正确配置系统时间服务,因为时间是日志文件的重要组成部分。

与 rsyslog 一起工作

rsyslog 服务集中收集 Linux 系统中不同应用程序的日志消息。它根据日志类型和优先级收集日志,并将其持久化存储在/var/logfollows:/目录中。

下表列出了一些由 rsyslog 维护的重要日志文件及其描述:

日志文件路径 描述
/var/log/messages 大多数标准日志消息都存储在这里,除了认证日志、邮件日志和一些应用程序调试日志。
/var/log/secure 存储认证日志,其中包含错误和其他消息。
/var/log/maillog 邮件服务器日志保存在这里。
/var/log/boot.log 启动/系统启动消息记录在这里。
/var/log/cron 存储 cron 作业(调度器)日志。
/var/log/wtmp 记录登录活动的日志保存在这里。
/var/log/dmesg 内核消息保存在这里。
/var/log/cups 打印服务日志保存在这里。
/var/log/samba Samba 服务日志存储在这里,不受 rsyslog 管理。Samba 服务直接在此处写入日志。
/var/log/httpd 此目录包含 Apache Web 服务器日志,不受 rsyslog 管理。Apache 直接将日志写入这些文件中。
/var/log/audit/ 包含 auditd 服务日志和 SELinux 日志文件。

Rsyslogd 是 Linux 系统中的一个应用程序,基于从 1980 年开始的 syslog 项目。它使用 syslog 协议在系统中记录事件,并具有某些扩展功能,例如 RELP 协议和缓冲操作支持。有时,在 Linux 中,syslog 也用于 rsyslog 的上下文中。

配置 rsyslogd 部分

rsyslogd 服务被 Linux 中的大多数应用程序用于记录事件。rsyslogd 服务使用三个主要组件处理系统中各种应用程序的日志消息:

  • 设施:代表进程类型

  • 优先级或严重性:代表消息的严重性

  • 目的地/位置:描述日志消息发送或记录的位置

rsyslogd 服务的配置文件存储在两个位置:

  • 在主配置文件,/etc/rsyslog.conf

  • 存储在 /etc/rsyslog.d/ 目录内带有 .conf 扩展名的文件

主配置文件,/etc/rsyslog.conf,包含了记录日志内容及存储位置的信息。它分为三个不同的部分,如下所示:

  • #### MODULES ####:模块部分用于配置 rsyslogd 的高级功能。

  • #### GLOBAL DIRECTIVES ####:全局指令部分用于指定全局可配置的参数。

  • #### RULES ####:这是最重要的部分,包含了指定记录内容及记录位置的规则。我们将在本章的 Rsyslogd 规则 部分详细讨论这一点。

可以通过 man 命令访问 rsyslog 的文档:

# man 5 rsyslog.conf

Rsyslogd 设施和优先级

设施代表生成日志消息的内部系统进程的固定列表。

下表列出了 CentOS 7 中可用的常见设施关键字及其描述:

设施 描述
auth 或 authpriv 代表与身份验证相关的子系统消息,如登录
cron 代表 crond 服务及任何定期应用程序消息
daemon 通用名称,用于表示各种守护程序子系统消息
kern 代表内核消息
lpr 代表 传统打印服务消息
mail 代表所有邮件程序消息
mark 仅供内部使用,不应与任何应用程序一起使用
news 代表由 NNTP 生成的消息
security 与 authpriv 相同,不再使用
syslog 代表 syslog 守护程序的消息
user 它代表由用户空间生成的消息
uucp 它代表由 UUCP 子系统生成的消息
local0-local7 它代表系统为用户提供的自定义未使用的设施,用于发送由用户定义的服务生成的消息
* 它匹配所有设施

优先级表示记录的消息的严重性或优先级。可以使用不同的优先级级别来确定可以记录的事件类型,例如debug、info、emerg、alert等,适用于指定的服务。

下表列出了严重性/优先级级别及其描述和分配的优先级数字:

分配的数字 优先级 严重性描述
0 emerg 当系统无法使用时生成消息
1 alert 必须立即采取行动,可用服务即将中止
2 crit 当发生关键条件时生成消息
3 err 非关键错误条件
4 warning 警告条件
5 notice 需要注意以防止未来问题的事件的信息性消息
6 info 为正常服务操作生成信息性消息
7 debug 用于服务操作的调试级别消息

如果在优先级字段中指定了通配符*,则表示所有类型的严重性(消息)。如果在严重性字段中写入none,则表示不会将对应设施的任何消息添加到指定的日志文件中。none用于防止相同的消息被记录到不同的日志文件中,如以下示意图所示:

Rsyslogd 规则

/etc/rsyslog.conf文件中的####RULES####部分包含用于定义消息日志记录的指令。该指令在/etc/rsyslog.conf文件中的语法如下:

facility.priority                        destination

以下是说明如何使用/etc/rsyslog.conf文件中定义的指令来记录消息的示例:

  • 要记录内核的所有信息消息,我们可以指定一个不同的日志文件,如下所示:
$ vi /etc/rsyslog.conf
kern.info /var/log/kernel
  • 我们在/var/log/目录中创建一个debug.log文件,用于收集所有服务的调试优先级消息,如以下命令行所示:
$ vi /etc/rsyslog.conf
*.debug /var/log/debug.log 
  • 在/etc/rsyslog.conf文件中进行所需更改后,重启 rsyslog 服务以使更改生效,如以下命令行所示:
$ systemctl restart rsyslog

在进行上述更改后,调试消息将不再出现在/var/log/messages文件中。

日志文件轮换

日志轮换可以防止/var/log目录填满。旧的日志文件在轮换时会被重命名为filename-datestamp。datestamp表示文件被轮换(归档)的日期,如下表所示:

现有日志 归档日志
/var/log/messages /var/log/messages-20180530 (2018 年 5 月 30 日轮换)

Logrotate 是定期轮换日志文件的工具。每晚会运行一个名为 /etc/cron.daily/logrotate 的 cron 作业来执行日志轮换。日志文件的轮换按照日志轮换程序的配置进行,配置文件存储在以下两个位置:

  • /etc/logrotate.conf

  • /etc/logrotate.d/*(该目录中的任何文件)

大多数日志文件是按周轮换的;然而,logrotate 命令会根据某些条件(例如达到一定大小)使某些日志文件轮换得更快或更慢。

在日志轮换后,日志查看程序会丢弃旧的日志文件归档以节省磁盘空间(通常为 4 周或在达到一定轮换次数后)。轮换时会创建一个新的日志文件,并通知相关服务。在安装新应用程序时,应用程序会通过将其日志配置文件放入 /etc/logrotate.d/ 目录中,来将日志文件添加到 logrotate 管理中。

创建自定义日志文件的示例如下:

# vi / etc/logrotate.d/<application_name>
/var/log/path_to_log_file {
rotate 3
size 2M
monthly
postrotate
/bin/systemctl reload httpd
endscript
}

以下是 log rotation 文件中使用的重要命令:

  • rotate 3:保留文件的最后三个版本,并删除最旧的版本

  • size 2M:当日志文件达到 2MB 时进行轮换

  • monthly:这是一个按大小的替代方法;如果文件大小未达到 2MB,则按月轮换文件

分析 syslog 条目

rsyslogd 服务生成的系统日志存储在 /var/log/ 目录中的多个文件里。最旧的消息保留在日志顶部,而新的日志条目按标准格式附加在日志文件的底部,如下图所示:

使用 tail 命令监控实时日志文件流量

在故障排除过程中,需要查看运行应用程序时生成的日志。使用带有 -f 选项的 tail 命令可以实现这一点。在一个终端中,我们会执行要故障排除的应用程序,在另一个终端中执行 tail 命令,如下所示:

# tail -f </path_of_log_file>

它显示指定文件名底部的 10 行,并保持文件打开,以便查看正在写入的新增行。一旦查看完日志后,可以按 Ctrl + C 关闭日志文件。

例如,要监控系统中的失败登录尝试,可以在一个终端中打开 /var/log/secure,在另一个终端中执行 ssh 命令,如下所示:

使用 logger 命令

尽管大多数应用程序已经配置为自动写入日志文件,但我们也可以使用logger命令将消息写入rsyslogd。logger命令根据logger命令中指定的设施和优先级,将日志消息写入日志文件。默认情况下,它将日志发送到名为“user”的设施,并具有名为“notice”的优先级(user.notice)。logger命令还可以在 shell 脚本中使用,以创建日志,如下例所示:

  • 如果我们将信息优先级的日志消息发送到rsyslog程序,它将被存储在/var/log/boot.log文件中,如以下命令行所示:
# logger -p local7.info  "Sample log entry using logger command"
  • 我们可以通过使用logger命令将任何日志消息发送到默认的日志文件/var/log/messages,如以下命令行所示:
# logger "Log file entry using logger"

欲了解更多有关日志记录的信息,请参考logger、tail、rsyslog.conf和logrotate命令的手册页。

使用systemd-journald

此守护进程为 CentOS 7 提供了一种非持久的高级日志管理方法,用于收集和显示来自内核、启动程序和其他运行中的服务的消息。journald以二进制格式维护这些消息,并可通过journalctl命令访问。默认情况下,日志是跨重启不可持久的。它将消息转发给rsyslogd进行永久性存储和处理。

使用journalctl命令查找事件

在 CentOS 7 中,systemd-journal存储在/run/log/journal/目录中,如下图所示:

当我们以 root 身份执行journalctl命令且不带任何选项时,它将显示完整的系统日志,从最旧的日志条目到最新的日志条目,如以下命令行所示:

# journalctl

journalctl命令使用颜色编码来突出显示消息的严重性,如下表所示:

优先级 日志中使用的文本高亮描述
Error、crit、alert 或 emerg 文字为红色
Notice 或 warning 文字为粗体
Info 或 debug 常规文本

使用不同的选项可以限制journalctl命令的日志搜索,输出到期望的结果:

  • Journalctl -n:默认情况下,使用-n选项与journalctl一起使用时,将显示最后 10 条日志条目。我们还可以指定要显示的日志条目的数量,如下图所示:

  • Journalctl -p:我们可以通过使用-p选项指定日志条目的优先级,来过滤日志输出。我们可以指定优先级的名称或编号,以显示指定或更高级别的日志条目,如下图所示:

  • Journalctl -f:-f选项类似于tail命令中的-f选项;它显示日志的最后 10 行,并保持打开状态,显示新写入日志中的条目,直到你按下Ctrl + C,如下面的截图所示:

限制 journalctl 输出到特定时间:journalctl命令可以使用两个选项,--since和--until,来指定时间范围,并显示该时间段内的日志消息。以下journalctl查询显示了18:05:00到18:10:00之间记录的所有日志:

# journalctl --since 18:05:00 --until 18:10:00

我们可以使用journalctl命令仅显示今天的日志条目,如下面的命令行所示:

# journalctl --since today 

我们还可以使用journalctl命令通过启用日志的详细输出,显示附加到日志条目的额外字段,如下面的命令行所示:

# journalctl -o verbose

下表列出了用于过滤查询的journalctl命令的一些重要字段:

字段名 描述
_COMM 基于命令名称过滤日志
_EXE 基于进程的可执行文件路径过滤查询
_PID 基于进程的 PID 过滤日志
_UID 基于运行进程的用户 UID 过滤日志
_SYSTEMD_UNIT 基于启动进程的 systemd 单元过滤日志

例如,可以使用以下命令过滤出来自 PID 为 1 的 systemd 进程的日志消息:

# journalctl _PID=1

journalctl命令还可以用来列出所有由sshd服务发送的日志消息,如下面的命令行所示:

# journalctl _SYSTEMD_UNIT=sshd.service 

journalctl命令还可以用来查看自上次启动以来的日志消息,如下所示的命令行所示:

# journalctl -b

配置systemd-journald以持久存储日志

systemd-journal存储在/run/log/journal目录中,该目录在系统重启时会被清除。它的配置文件是/etc/systemd/journald.conf,可以用来微调日志参数,如用于存储日志的文件系统大小(默认值为 10%)。

systemd-journal的配置方式是,如果系统中存在/var/log/journal/目录,则日志条目将记录在该目录中,而不是/run/log/journal/。同样的概念也用于使systemd-journal的存储在重启后保持持久。为了使systemd-journal持久化,需要执行以下步骤:

  1. 作为 root 用户创建/var/log/journal/目录,如下面的命令行所示:
# mkdir /var/log/journal

  1. 将创建的目录的所有者设为 root,组设为systemd-journal,权限设为2755,如下面的命令行所示:
# chown root:systemd-journal /var/log/journal
# chmod 2755 /var/log/journal
  1. 重启系统或向systemd-journald发送USR1信号,如下面的命令行所示:
# killall -USR1 systemd-journald
  1. 通过列出一个包含日志文件的新目录,确保 systemd-journal 在重启后持久化,目录位于 /var/log/journal 目录中,如以下命令所示:
# ls /var/log/journal

理解如何控制系统和服务

从用户或系统管理员的角度来看,了解如何管理系统上安装的各种服务是至关重要的。用户应该能够在启动时启用服务,并在需要时启动或停止服务。

早期,Linux 系统和服务由 SysV init 或 BSD init 管理。后来,通过添加像 service 和 chkconfig 这样的工具,结合 shell 脚本,进一步改进了它们的管理。更近期,从 CentOS 7 开始,系统和服务的管理由 systemd 负责。systemd 取代了 CentOS 7 中的 initd,成为第一个进程。

在接下来的章节中,你将学习如何管理系统上运行的服务。你将学习如何使用 systemd 及其组件,这些组件负责将系统从内核空间切换到用户空间,并在此后管理系统进程。

定义基本术语

在本节中,我们将定义与系统和服务管理相关的基本术语。

什么是守护进程?

守护进程是一个等待或在后台运行的进程,执行多个任务。它通过网络套接字监听连接。

什么是套接字?

当客户端连接建立时,系统会创建一个套接字,并将其传递给守护进程,或者为自己创建一个守护进程。在 Linux 中,套接字主要用于建立客户端与守护进程之间的通信。

什么是 systemd?

从 CentOS 7 起,systemd 取代了 init 进程,成为内核启动时启动的第一个进程(PID=1)。它通过为应用程序和内核之间提供接口,管理 Linux 内核中的系统和服务。启动 systemd 后,它开始记录活动、挂载文件系统和设备、启动其他服务,并最终提供用户登录的 shell。systemd 通过不同的库和工具(如 systemctl、journalctl、hostenamectl、localectl、timedatectl、systemd-cgls 等)来执行这些任务,并且在安装 systemd 时会一并安装这些工具。它通过称为单元(units)的对象来管理各种系统资源。

什么是单元?

在 systemd 中,单元是 systemd 知道如何管理和操作的对象。它们代表不同的系统资源,并通过称为单元文件的配置文件定义。默认情况下,这些单元文件保存在 /usr/lib/systemd/system/ 目录下。只有那些单元文件存储在 /lib/systemd/system 目录下的单元,才能在会话期间启动或停止。这些文件由应用程序的 RPM 文件安装到系统中。单元是 CentOS 7 之前使用的旧 init 脚本的替代品。

什么是 systemctl?

它是 CentOS 7 中service和chkconfig命令的替代品。systemctl命令用于管理不同类型的systemd对象(单元)。systemd有 12 种单元类型,可以通过以下截图中的命令列出:

以下表格列出了一些常见单元及其描述:

单元类型 描述
服务 这类单元具有.service扩展名,表示系统服务。此单元用于启动守护进程,例如 Web 服务器。如果没有指定单元名称,systemctl默认将服务作为默认单元。
套接字 这类单元具有.socket扩展名,表示进程间通信(IPC)套接字。
路径 这类单元具有.path扩展名,用于在特定的文件系统更改发生之前延迟激活服务。
目标 这类单元具有.target扩展名,表示一组单元。
切片 这类单元具有.slice扩展名,表示进程的管理单元。

使用 systemd 和 systemctl

本节介绍了 systemd 和 systemctl 是如何组织的,以及如何使用 systemd 管理重要的对象(单元)。

使用systemctl查看服务状态

服务单元是systemd中最重要的单元之一,通过systemctl进行管理。如果未指定单元类型,systemctl将显示服务单元的状态(如果存在)。查看任何单元的语法如下:

# systemctl     status    name.type

这里,name 是服务名称,type 是单元类型,例如服务、套接字、路径等。以下截图中的示例说明了如何使用systemctl命令查看服务状态:

以下表格列出了服务的各种状态及其描述:

状态 描述
Loaded 单元配置文件已成功处理
Active (running) 正在运行并有一个或多个活动进程
Active (exited) 成功完成了一次性的配置
Active (waiting) 正在运行并等待事件发生
Inactive 当前未运行
Enabled 启动时会启动
Disabled 启动时不会启动
Static 不能直接启用,但可以由其他启用的单元自动启动

使用systemctl查看单元文件

作为系统管理员或用户,有时需要了解当前systemd单元文件的状态。这有助于系统的优化。我们可以使用systemctl命令将服务配置为在系统启动后处于活动和加载状态,或者处于非活动状态。

以下表格列出了用于查看单元文件的命令及其描述:

命令 描述
# systemctl 显示所有已加载并在启动时激活的单元的状态
# systemctl --type=service 或 # systemctl list-units --type=service 显示所有活动服务单元的状态
# systemctl --type=service –all 或 # systemctl list-units --type=service --all 显示所有已加载的服务单元的状态,无论其是否活动
# systemctl --failed --type=service 显示所有失败的服务
# systemctl is-active sshd 显示特定服务当前是否处于活动状态
# systemctl is-enabled sshd 显示特定服务是否已启用在启动时自动启动
# systemctl list-unit-files --type=service 显示所有指定类型单元的启用、禁用或静态设置
# systemctl status sshd.servisystemctlce -l 显示有关指定服务的详细状态信息

单元依赖关系和单元文件结构

服务可以作为独立的单元启动,也可以作为其他服务的依赖项启动。例如,假设启用了一个套接字单元,但具有相同套接字名称的服务单元未启用,那么当网络套接字收到请求时,该服务将自动启动。类似地,当文件系统路径条件满足时,服务也可以由路径单元触发。以下命令用于列出指定单元的依赖关系树:

# systemctl list-dependencies sshd

从 CentOS 7 开始,systemd提供了一个统一的接口,用于从它们的存储位置启动单元文件。系统中存储的单元文件位置如下:

  • /usr/lib/systemd/system/:它包含系统默认的单元文件。

  • /etc/systemd/system:它包含用于修改 systemd 默认行为的系统特定参数。

  • /run/systemd/system/:它包含单元文件的运行时配置。

单元文件的结构如下图所示:

前面的单元文件可以分为以下三个部分:

  • 单元:此部分描述单元类型及其依赖关系(如果有)。它还包含After语句和Before语句。这些语句定义了单元的依赖关系。Before语句表示该单元应在指定单元之前启动。After语句表示该单元应在启动指定单元后启动。

  • 服务:此部分包含有关如何启动和停止服务的描述。以ExecStart参数开头的行描述如何启动单元,以ExecStop参数开头的行描述如何停止单元。

  • 安装:此部分包含一行以WantedBy参数开头,表示该应用程序的目标。目标单元相当于 CentOS 6 及之前版本中的运行级别。

使用 systemctl 管理守护进程

可以通过在 systemd 配置目录中创建指向单元文件的链接来在启动时启动服务,方法是使用systemctl命令。早期自动启动服务的方法是使用chkconfig。下面的示例展示了如何使用systemctl命令禁用或启用单元文件:

屏蔽服务

为了防止执行某些功能的相似服务之间发生冲突,使用了屏蔽。举例来说,CentOS 7 中有iptables和firewalld这两种防火墙服务;但是,建议同时只使用其中一个。因此,屏蔽了其中一个防火墙服务,以防止两者之间的冲突。屏蔽通过创建指向/dev/null的服务文件symlink来防止服务的意外启动,如下图所示:

如果一个服务被禁用,它将不会在启动时自动启动,即使是通过其他单元文件;然而,用户仍然可以手动启动该服务。被屏蔽的服务具有优势,因为它既无法手动启动,也无法自动启动。

以下表格列出了用于管理服务的不同systemctl命令:

命令 描述
# systemctl status <unit> 显示单元状态的详细信息
# systemctl stop <unit> 停止正在运行的服务
# systemctl start <unit> 启动已停止的服务
# systemctl restart <unit> 重启(停止然后启动)一个服务
# systemctl reload <unit> 通过重新读取配置文件来重新加载正在运行的服务的配置
# systemctl mask <unit> 完全禁用服务在启动时自动启动,或在任何时候手动启动
# systemctl unmask <unit> 解屏蔽一个被屏蔽的服务,使其可以被用户启用或手动启动
# systemctl enable <unit> 设置服务在启动时自动启动
# systemctl disable <unit> 禁用服务在启动时自动启动
# systemctl poweroff 关闭系统
# systemctl reboot 重启系统

使用 systemd 控制启动过程

在启动过程中,当内核镜像和 initramfs 镜像加载时,initramfs 会启动系统上的第一个进程,即 process ID 为 1 的 systemd 进程。这个 systemd 进程在系统启动的最后阶段接管控制,并执行以下操作:

  • 从/etc/systemd/目录读取配置文件

  • 读取/etc/systemd/system/default.target链接的文件

  • 执行/etc/rc.local文件

Systemd 目标单元负责在系统启动后自动确定和启动服务。在本节中,我们将学习如何控制在启动时执行一组服务。这些服务将共同定义系统的状态,例如单用户模式或启用网络的多用户模式等。

什么是 systemd 目标?

目标单元用于分组和排序其他单元。systemd 通过目标单元的帮助,管理同时启动多个相关进程。一些目标,如 multi-user.target,定义了系统的特定状态,可以视为 SysV 运行级别的更强大和灵活的等价物。与此同时,其他目标除了有效地管理依赖关系外,并没有提供任何额外的功能。目标单元的配置文件存储在 /usr/lib/systemd/system 目录下。

以下表格列出了重要的目标、它们的等效运行级别以及描述:

等效运行级别 目标单元 描述
0 poweroff.target 关闭并关闭系统
1 rescue.target 进入 Sulogin 提示符,并进行基本系统初始化
2, 3, 4 multi-user.target 仅支持非图形化多用户基于文本的登录
5 Graphical.target 图形多用户模式和基于文本的登录
6 Reboot.target 关闭并重启系统

一些目标是另一个目标的组成部分:graphical.target 包含 multi-user.target,而 multi-user.target 又依赖于 basic.target 等其他目标。我们可以通过执行以下截图中显示的命令行查看这些依赖关系:

我们可以通过以下命令查看当前正在运行的系统中加载的可用目标:

# systemctl list-units --type=target --all

我们可以通过以下命令查看系统上安装的所有目标:

# systemctl list-unit-files --type=target --all

在运行时切换目标

在 CentOS 7 中,管理员可以通过使用 systemctl isolate 命令在运行时切换到不同的目标(运行级别),这一操作在 CentOS 6 中是通过 telinit 命令完成的。我们只能隔离到那些在其单元文件中设置了 AllowIsolate=yes 的目标。例如,我们可以通过以下命令从 graphical.target 切换到 multi-user.target:

# systemctl isolate multi-user.target

上述命令将使用户进入运行级别 3。要切换回运行级别 5,请执行以下命令:

# systemctl isolate graphical.target

更改系统的默认目标

在系统启动时,systemd 激活 default.target,通常它是 /etc/systemd/system/ 目录中的一个符号链接,指向 graphical.target 或 multi-user.target。它相当于默认的运行级别,系统管理员以前会在 /etc/inittab 文件中进行设置。

以下表格列出了用于管理默认目标的 systemctl 命令及其描述:

命令 描述
# systemctl get-default 查看当前的默认目标
# systemctl set-default graphical.target 将默认目标设置为 graphical.target(图形界面 Shell)
# systemctl set-default multi-user.target 将默认目标设置为 multi-user.target(基于文本的 Shell)

使用 systemctl 命令更改默认目标的示例如下所示:

理解 SELinux 概念

SELinux 是一种额外的安全层,用于保护系统。用户手动设置的权限是一种安全控制,作用于用户的自定义操作,而 SELinux 是强制访问控制,用于保护系统安全。其主要作用是在系统服务遭到破坏时保护数据。SELinux 由一组安全规则组成,这些规则决定了哪个进程可以访问哪些文件、目录或端口。

SELinux 上下文

当 SELinux 在系统中被强制执行时,它会检查哪些进程可以访问哪些文件、目录和端口。每个文件、进程、目录和端口都有一个特殊的安全标签,称为 SELinux 上下文,它是用来确定进程是否可以访问某个文件、目录或端口的名称。默认情况下,策略不允许任何交互,除非明确的规则授予访问权限。

SELinux 标签具有不同的上下文:用户、角色、类型和敏感性。针对性策略是 CentOS 7 中启用的默认策略,它根据第三个上下文(即类型上下文)定义规则。类型上下文的名称通常以 _t 结尾。

查看 SELinux 上下文

大多数 Linux 命令都带有 -Z 选项,用于显示 SELinux 上下文。例如,ps、ls、cp 和 mkdir 都使用 -Z 选项来显示或设置文件、目录、进程或端口的 SELinux 上下文。

以下是一些示例,展示了如何与多个命令一起使用 -Z 选项来显示 SELinux 上下文:

  • ps 命令可用于查看进程及其 SELinux 上下文:
# ps axZ
  • ps 命令也可以与选项 -ZC 一起使用,以查看指定进程的 SELinux 上下文,如以下示例所示:
# ps -ZC sleep
  • ls 命令可以与 -Z 选项一起使用,以查看目录中文件的 SELinux 上下文,如以下命令行所示:
# ls -Z /home
# ls -Z /var/www
  • cp 命令可以与 -A 选项一起使用,在执行复制操作时保持文件或目录的 SELinux 上下文,如以下命令行所示:
# cp -A /tmp/demo /var/www/html/

通常,在我们使用 vim、cp 或 touch 命令创建新文件时,子目录会被分配与父目录相同的上下文。

为了更清楚和深入地理解 SELinux 的概念,我们可以考虑在没有 SELinux 控制和启用 SELinux 控制下 Apache Web 服务器的工作方式:

  • 在没有 SELinux 的情况下:在这种情况下,网页服务器运行在端口 80 上,该端口已在防火墙中打开以允许访问服务网页。假设攻击者通过 Apache 服务中的漏洞入侵了服务器。在入侵后,攻击者将获得以 Apache 用户和 Apache 组权限访问文档根目录的权限。因此,攻击者可以在/var/www/html/、/tmp 和 /var/tmp 目录中创建和写入文件。

  • 在启用 SELinux 强制模式的情况下:在这种情况下,SELinux 会检查目标策略中给出的规则,这些规则基于类型上下文。Apache 网页服务器进程的 SELinux 上下文类型为 httpd_t,/var/www/html 中的文件和目录的 SELinux 上下文类型为 httpd_sys_content_t。 /tmp 和 /var/tmp 目录中的文件和目录在强制模式下的 SELinux 上下文类型为 tmp_t。

目标策略规则允许作为 httpd_t 运行的进程访问具有 httpd_sys_content_t 上下文的文件和目录,因此不允许访问 /tmp/ 和 /var/tmp/ 中的文件或目录。因此,即使恶意用户入侵了网页服务器,他们也无法在 /tmp/ 或 /var/tmp 目录中创建或写入文件。用户造成的损害将仅限于 /var/www/html 文件夹,如下图所示:

使用 SELinux

本节介绍了用于管理 SELinux 上下文和应用于文件、目录、进程和端口的强制策略的各种命令。

更改 SELinux 模式

SELinux 有三种操作模式,如下表所示:

SELinux 模式 描述
强制 在此模式下,规则可用且已应用。SELinux 记录活动并保护系统。
宽容 在此模式下,规则可用但不应用。此模式主要用于故障排除。此模式用于临时允许访问 SELinux 在强制模式下限制的内容。在此模式下,SELinux 记录被拒绝的操作。无需重新启动系统即可从强制模式切换到宽容模式,反之亦然。
禁用 在此模式下,规则不可用。它完全禁用 SELinux。为了禁用或从强制模式或宽容模式切换到禁用模式,系统需要重新启动,因为它会完全重新标记文件。

使用 setenforce 进行运行时更改

我们可以通过使用 setenforce 命令在运行时将 SELinux 模式从强制模式更改为宽容模式,反之亦然。在更改 SELinux 模式之前和之后,我们必须使用 getenforce 命令确保当前模式。

以下是说明 setenforce 和 getenforce 命令使用的示例:

  • 要显示当前的 SELinux 模式,请使用以下命令:
# getenforce
  • 要将当前 SELinux 模式从强制模式更改为宽容模式,请使用以下命令之一:
# setenforce 0 or
# setenforce Permissive

  • 要将当前 SELinux 模式从宽松模式切换为强制模式,可以使用以下任一命令:
# setenforce 1 or# setenforce Enforcing
  • 要查看详细的 SELinux 信息,请使用以下命令:
# sestatus

临时更改 SELinux 模式的另一种方法是在启动时向内核传递一个参数。传递enforcing=0的内核参数将使系统在该实例中以宽松模式启动,而selinux=1将使系统以强制模式启动。

设置 SELinux 的默认模式

SELinux 的配置文件是/etc/selinux/config。它决定了 SELinux 在启动时的模式和策略。我们可以修改/etc/selinux/config文件,将SELINUX=permissive参数设置为改变 SELinux 的默认模式,如下图所示:

在 CentOS 的早期版本中,SELinux 配置文件存储在/etc/sysconfig/selinux中。现在,在 CentOS 7 中,该文件是/etc/selinux/config的符号链接(symlink)。

如果在启动时传递了enforcing=0(用于宽松模式)或selinux=0(用于禁用 SELinux)的内核参数,那么它将覆盖/etc/selinux/config中设置的当前配置。

修改文件上下文

如前所述,通常情况下,父目录的 SELinux 上下文会被分配给新创建的文件,前提是该文件是通过vim、cp或touch命令创建的。

如果文件使用mv命令移动,或使用cp -a命令复制,则原始的 SELinux 上下文将保持不变。

通常,我们需要根据目标目录修改文件上下文,以便在需要时进程可以访问文件对象。在接下来的章节中,我们将讨论可以用来实现这一目标的不同工具。

使用restorecon恢复默认上下文

使用restorecon命令是修改文件或目录 SELinux 上下文的最常用且首选的方法。顾名思义,restorecon命令用于通过读取 SELinux 策略中设置的默认规则来恢复文件或目录的默认上下文。如果应用了错误的上下文,restorecon会根据文件系统的策略自动修正。

在以下示例中,我们模拟一个问题场景,其中一个文件具有不正确的语法,并使用restorecon命令进行修正:

restorecon命令是policycoreutil包的一部分,因此要使用此命令,必须在系统上安装该包。

使用chon进行上下文管理

chcon命令也可以与_t选项一起使用来更改文件的上下文。这种修改文件上下文的方法不推荐使用,因为使用时可能会发生错误。chcon命令在使用时会将新上下文写入文件系统,但策略本身不会改变。因此,使用此命令所做的更改将在重新标记文件系统上的 SELinux 上下文时被覆盖。

chcon 命令的使用示例如下图所示:

使用 semanage 进行上下文管理

semanage 命令将新上下文写入 SELinux 策略,用于在文件标签重新标记或通过 restorecon 设置默认文件上下文时应用文件上下文。它使用扩展正则表达式来指定路径和文件名,以应用这些规则(新文件上下文)。semanage fcontext 最常用的扩展正则表达式是 (/.*)?。该表达式匹配表达式前列出的目录及该目录下的所有内容(递归匹配)。

semanage 命令使用示例如下图所示:

semanage 命令是 policycoreutil-python 包的一部分。要使用 semanage 命令,请确保此软件包已安装在系统中。

修改端口上下文

SELinux 不仅仅是基于 SELinux 标签限制进程对文件的访问。它还可以通过限制服务访问未经授权的端口来控制网络流量。默认情况下,SELinux 策略允许 ssh 服务访问端口 22/TCP。在以下示例中,我们允许 ssh 在除默认端口外的另一个端口 2525/TCP 上运行,如下所示:

  1. semanage 命令可与 port 子命令一起使用,列出分配给服务的当前端口,如下图所示:

  • 我们还可以使用 semanage 命令为特定服务授予对任何自定义端口的访问权限。在以下截图中,semanage 命令被用来将选定的端口添加到特定服务的访问列表中:

  • semanage 命令还可以用来移除端口与特定服务的关联,如以下截图所示:

管理 SELinux 布尔值

SELinux 布尔值是开关,包含一组规则,用于选择性地调整 SELinux 策略的行为。SELinux 布尔值提供了一个简便的接口来改变 SELinux 策略规则的行为。

以下是说明如何使用 getsebool 和 setsebool 命令管理 SELinux 布尔值的示例:

  • getsebool 命令可与 -a 选项一起使用,显示所有 SELinux 布尔值及其当前值,如以下命令行所示。该命令的输出将传递给 grep 过滤器,以缩小结果范围:
# getsebool -a
  • getsebool -a 命令的输出可以通过 grep 进行过滤,如以下命令行所示:
# getsebool -a | grep ftp
  • setsebool 命令可用于在运行时修改(开启或关闭)SELinux 布尔值,如以下命令行所示:
# setsebool ftp_home_dir on
  • 使用setsebool命令并加上-P选项,修改 SELinux 布尔值的运行时值和默认值,如下命令所示:
# setsebool -P ftp_home_dir on

管理 SELinux 故障排除

SELinux 提供了一个额外的安全层,超越了用户设置的自由访问控制。它防止任何未授权的进程尝试访问资源,如文件。这里,尝试访问资源的进程可能是一个合法进程,也可能是一个已被攻陷的进程。禁用 SELinux 并不被认为是良好的做法。有时,当从第三方安装二进制文件或应用程序时,它们可能没有适当的 SELinux 上下文,这可能会导致该服务无法正常运行。在这种情况下,SELinux 会以宽松模式运行,并根据日志文件中捕获到的拒绝服务信息创建新规则。在大多数 SELinux 故障排除的案例中,观察到 SELinux 由于文件上的错误类型上下文而应用了访问控制限制。这个问题可以通过使用restorecon命令轻松解决,该命令将根据策略中的 SELinux 规则设置文件的默认上下文。通过这种方法,我们可以保持 SELinux 在强制模式下运行,并确保系统的安全性。

通过打开和关闭 SELinux 布尔值来修改 SELinux 的模式,有时也用于放宽或加强服务运行的 SELinux 控制。为了在 SELinux 规则或策略中做出适当的更改,首要要求是正确理解问题。在这方面,通过查看日志来监控 SELinux 违规起着重要作用。为了将 SELinux 消息记录到/var/log/messages和/var/log/audit/audit.log中,并以易于理解的格式显示,系统应安装setroubleshoot-server包,可以通过以下命令实现:

# yum install setroubleshoot-server -y

使用 sealert 进行故障排除

每个 SELinux 违规事件都会分配一个唯一的标识符(UUID)。此 UUID 与sealert命令一起使用,用于生成特定事件的报告摘要。

例如,我们在 root 用户的主目录中创建一个文件,然后将该文件移动到/var/www/html/目录。现在,尝试通过网页浏览器或使用curl命令行工具访问该文件,如下图所示:

现在,可以使用 UUID 和sealert命令查看 SELinux 违规的错误报告,如下图所示:

在应用sealert报告中给出的 SELinux 违规建议后,错误将被修复,并允许使用curl命令访问文件,如下截图所示:

理解 CentOS 7 中的防火墙概念

操作系统安全通常遵循深度防御模型,其中安全性在系统的不同层级上实现。从政策和程序、物理控制、网络边界安全、主机安全、应用程序安全等多个元素来加固系统安全。在此过程中,防火墙通过限制对系统的访问,帮助保护系统及应用程序。防火墙规则根据特定标准过滤数据包,如 IP 地址、端口和协议等。

在 Linux 中,防火墙规则由内核中可用的网络过滤子系统(称为netfilter)进行管理。netfilter 框架使系统能够以编程方式检查、修改、丢弃或拒绝任何进入、出去或转发的网络数据包。

iptables命令是与 netfilter 交互并管理防火墙的最常用工具。iptables命令仅管理防火墙中的 IPv4 规则。对于 IPv6 规则的管理,使用ip6tables命令;对于软件桥接,使用ebtables工具。然而,使用iptables工具管理防火墙并不友好,需要对防火墙和iptables命令有很好的理解。因此,为了克服iptables的复杂性并引入一些高级功能,设计了一个新工具firewalld。

firewalld 概念

在 CentOS 7 中,引入了一个名为firewalld的新工具,用于与 netfilter 交互。它可用于配置和监控 IPv4、IPv6 以及软件桥接的防火墙规则。此外,应用程序可以通过firewalld与防火墙规则交互,例如请求通过 D-bus 消息系统打开端口。firewalld 支持运行时配置和持久性配置。在 CentOS Base 安装中默认安装,但如果没有安装,用户可以使用以下命令行进行安装:

# yum install firewalld -y
# systemctl start firewalld 
# systemctl enable firewalld

firewalld 与iptables服务不兼容,因此强烈建议不要在同一系统上同时使用它们。可以选择使用firewalld并禁用iptables(iptables、ip6tables和ebtables),或使用iptables并禁用firewalld。

firewalld 区域

firewalld 将进入流量划分为不同的区域。每个区域是一组规则的集合。为了选择使用哪个区域来处理进入连接,firewalld 按照以下三个规则按给定顺序进行匹配:

  • 进入数据包的源地址与为该区域配置的源地址规则进行匹配。如果源地址匹配,则数据包通过该区域路由。

  • 如果源地址不匹配,则数据包的进入接口将与为该区域设置的接口进行匹配,并使用该区域。

  • 如果数据包的传入接口或数据包的源地址都不匹配,则会应用默认区域中给定的规则。默认区域是系统或用户定义的其他区域之一。默认情况下,公共区域被设置为默认区域。以下截图展示了使用firewall-cmd列出可用区域和默认区域的示例:

以下表格列出了firewalld中可用的预定义区域及其描述:

区域 描述
trusted 允许所有传入流量。
home 此区域用于家庭网络。在此区域,所有传入流量都会被拒绝,除非与传出流量相关,或与该区域的预定义服务匹配,例如ssh、mdns、ipp-client、samba-client或dhcpv6-client。
internal 此区域的规则与家庭区域定义的规则相同。通常用于内部网络。
work 在此区域,所有传入流量都会被拒绝,除非与传出流量相关,或与该区域的某些预定义服务匹配,例如ssh、mdns、ipp-client或dhcpv6-client:
public 在此区域,所有传入流量都会被拒绝,除非与传出流量相关,或与该区域的某些预定义服务匹配,例如ssh或dhcpv6-client。
external 在此区域,所有传入流量都会被拒绝,除非与传出流量相关,或与该区域的某些预定义服务匹配,例如ssh。从该区域转发的传出 IPv4 流量会进行伪装(NAT),使其看起来来自于传出的网络接口。
dmz dmz是非军事区。只允许选择性的传入连接,这些连接对内部网络的访问受到限制。所有其他流量都会被拒绝。
block 拒绝所有传入流量,并发送icmp-host-prohibited消息。只允许与系统传出流量相关的连接的传入流量。
drop 在此区域,所有传入流量都会被丢弃(没有任何 ICMP 错误),除非与传出流量相关。

Firewalld 服务

firewalld 的另一个主要组成部分是服务。某些默认服务用于允许或拒绝特定端口上网络服务的流量访问。每个服务都有一个配置文件,描述其要求,例如服务操作所需的 TCP 或 UDP 端口。用户可以使用以下截图所示的命令列出 firewalld 中所有可用的服务:

对于 firewalld 的安全配置,应该在正确的区域中允许每个服务的访问。

服务配置文件存储在以下两个目录中:

  • /usr/lib/firewalld/services

  • /etc/firewalld/services

这些服务文件以 XML 格式配置。以下截图显示了 ftp.xml 文件的示例:

管理 firewalld

Firewalld 可以通过以下两种方式进行管理。

使用 firewalld-cmd 命令行工具

这是管理 firewalld 配置(无论是运行中的还是永久性的)最常用的方法。在本节中,我们描述了使用此工具管理 firewalld 的方法。它可以执行使用 firewalld-config GUI 工具执行的所有操作。此工具是 firewalld 包的一部分。

使用 firewalld-config 图形工具

Firewall-config 是一个图形工具,用于修改和查看 firewalld 的运行(内存中)配置以及永久(硬盘上)配置。此工具是 firewall-config 包的一部分。通过在命令行输入 firewall-config 来启动该工具。

firewalld 的配置文件存储在 /etc/firewalld/ 目录下。Firewalld 支持两种类型的配置:

  • 运行时或内存中的配置:firewalld 的内存配置会在重新加载 firewalld 或系统重启后丢失。

  • 永久或磁盘配置:该配置在重启后仍然有效,并在重新加载 firewalld 时应用。

使用 firewalld

在启动 firewalld 之前,我们需要确保 iptables、ip6tables 和 ebtables 未运行,因为它们与 firewalld 冲突。

以下是说明 firewalld-cmd 命令用法的示例:

  1. 使用以下命令停止与 iptables、ip6tables 和 ebtables 冲突的服务:
# systemctl stop iptables
# systemctl mask iptbales
# systemctl stop ip6tables
# systemctl mask ip6tables
# systemctl stop ebtables
# systemctl mask ebtables
  1. 以下命令用于在 CentOS 7 中 启动 和启用 firewalld:
# systemctl start firewalld
# systemctl enable firewalld
# systemctl status firewalld
  1. 现在,配置 firewalld 的第一步应该是检查默认配置的现有区域和服务,以及用户未配置的区域和服务:
    • 使用以下命令行列出 firewalld 中的所有区域:
# firewall-cmd --get-zones 
    • 使用以下命令行仅列出 firewalld 的活动区域:
# firewall-cmd --get-active-zones
    • 使用以下命令行列出当前的默认区域:
# firewall-cmd --get-default-zone
    • 使用以下命令行列出可与 firewalld 配置的服务:
# firewall-cmd --get-services
  1. 在对 firewalld 配置进行任何更改后,必须重新加载它以使更改生效。默认情况下,所有更改仅为运行时更改。我们可以使用 --permanent 选项将其设置为永久配置,这样配置在重启后也会保留。现在,让我们通过以下 firewalld-cmd 命令更改默认区域:
# firewall-cmd --set-default-zone=internal

更新默认区域后,我们应该使用以下命令行确认当前默认区域的设置:

# firewall-cmd --get-default-zone
  1. 现在,让我们通过以下命令行使用 firewall-cmd 将端口永久添加到公共区域:
# firewall-cmd --permanent --zone=internal --add-port=80/tcp --permanent

在上述命令中,如果我们没有添加--permanent选项,那么更改将在重新加载firewalld配置后丢失。我们可以通过以下命令行重新加载firewalld配置:

# firewall-cmd --reload

现在,查看在firewalld中最近添加的 TCP 端口80的状态:

# firewall-cmd --zone=internal --list-ports

我们还可以使用firewall-cmd命令查看区域的完整配置。在以下示例中,我们列出了内部区域的完整配置:

# firewall-cmd --zone=internal --list-all
  1. 在以下示例中,我们使用firewall-cmd命令将 TCP 端口80从内部区域中移除,如以下命令行所示:
# firewall-cmd --zone=internal --remove-port=80/tcp
  1. 向firewalld中的一个区域添加服务。以下示例展示了如何将ftp服务添加到firewalld的内部区域:
# firewall-cmd --zone=internal --add-service=ftp
  1. 使用以下命令行列出一个区域中的服务:
# firewall-cmd --list-services --zone=internal
  1. 使用以下命令行从firewalld中的一个区域移除服务:
# firewall-cmd --zone=internal --remove-service=ftp
  1. 用户可以在网络发生泄露时,通过使用firewall-cmd的 panic 选项来丢弃活动连接的所有进出数据包,如以下命令行所示:
# firewall-cmd --panic-on

执行上述命令后,系统上的任何 ping、ssh或与 Web 相关的活动将被阻止。要关闭此功能,请执行以下命令:

# firewall --panic-off

除了我们在本节中讨论的firewall-cmd配置规则外,firewalld 还有两种添加防火墙规则的方式,即直接规则和丰富规则。

总结

在这一章中,我们首先学习了 Linux 系统中的不同类型的日志记录,以及如何有效地使用它们进行调试和故障排除。接着,我们学习了如何管理系统服务以优化系统性能。随后,我们理解了 SELinux 的概念,以加固应用程序和系统的安全性。最后,我们学习了如何使用firewalld框架过滤系统中的进出数据包。

Linux 的核心理念是通过实践学习。如果你在每一章节中都练习了所给的命令,并结合理论部分,你会在使用 Linux 时感到更加得心应手。本书是为初学者编写的,但即使是经验丰富的 Linux 用户,也能从每一章中学到一些东西。至此,我们关于使用 CentOS 7 操作系统启动 Linux 的精彩旅程也画上了句号。如果你有任何问题,欢迎向我咨询。你可以通过shiwangkalkhanda@outlook.com与我联系。

posted @ 2025-07-05 15:45  绝不原创的飞龙  阅读(78)  评论(0)    收藏  举报