序言

你将学到什么

本书是为计算机相关专业的Linux基础课程编写,也适合初学Linux的读者。如果你有些基础,本书也能查漏补缺。不要一次性看完本书,需要什么看什么,才是正确方法。

本书降低了Linux学习门槛,让读者有选择的在十分钟甚至一分钟内解决问题,快速、简单、连续、基础是本书的基本原则。本书还介绍了很多重要的Linux使用技巧,也提供了有关远程主机连接设置、文件检索、文档查询等内容。

应当具备的基础知识

本书假设读者已经掌握基本的计算机知识:

  • 了解鼠标、键盘、屏幕、硬盘(分区)、WIFI、网线等常用电脑软硬件;

  • 了解Windows控制面板,了解如何在Windows上安装软件;

  • 有简单的网络知识,比如IP地址;

  • 对Linux有简单的认识,知道或听说过Linux发行版名称。

本书假设读者没有Linux基础,内容安排是从零开始的。因此,对于那些不是计算机相关专业的读者来说,本书也是适用的。 需要指出的是,根据读者不同的知识背景,本书有多种不同的学习方案。对于那些有较强计算机基础的读者来说,可以有选择地学习。

关于Linux

通过本入门指南学习Linux基础,你将借助Linux强大的魔力、经验和技巧让生活更轻松,效果立竿见影。本书内容教你如何使用终端学习Linux,旨在为你打下坚实的基础,让Linux为你服务。最终,你不会成为Linux专家。如果这是你想要的(你应该这样做,这会让你变得更好),你会在路上一帆风顺,拥有正确的知识和技能来帮助你达到目标。

你将按照我准备的十章入门指南学习Linux。这里有直白的文字、命令说明、例子、捷径和最佳实践。

首先,Linux看起来令人生畏、复杂和害怕。实际上,Linux非常简单直接(学过的人都这么说),一旦你完成了下面的部分,你就会明白发生了什么。

Linux的哲学:每个程序只做一件事。 Linux提供一堆砖块,你用砖块组合创造出特定的工具(集),用来解决某件事情。只要有一点创造力和逻辑思维,加上对程序模块工作方式的理解,你就可以组装出几乎能做任何事的工具(集)。我喜欢 "偷懒" 才用Linux。

可能有个问题在你脑子闪过,
"为什么我要麻烦学习Linux?图形界面更好用,也能很好的完成我所想的。"

某种程度上你是对的,我绝对不建议你抛弃图形界面。有些任务适合图形界面,文字处理、视频编辑是最好的例子。同时,有些任务更适合Linux,比如数据处理(报告)、文件管理。在这两种环境中,有些任务处理起来又没什么不同。将Linux加入你的武器库,才能如虎添翼。像往常一样,挑选合适的工具做事。

本书的组织

本书分为十三个章节。通常,我推荐你按顺序学习。假如你阅读本书是为了特定的需求,请忽略我的建议。你现在可以开始学习,或者阅读下面的内容,进一步了解本书。

  1. 安装虚拟机 - 熟悉虚拟机软件基本使用,并安装CentOS7;

  2. 客户端工具 - 介绍客户端工具,怎样使用工具连接远程主机;

  3. 传输文件 - 学习怎样用MobaXterm或 scp 命令上传下载文件或目录;

  4. 文件、目录与路径 - 了解什么是文件,什么是目录,认识相对路径和绝对路径;

  5. 文件和目录管理 - 练习文件和目录的创建、查看、编辑、压缩和解压等基础操作;

  6. 文件属性 - 了解用户、组和文件权限,熟悉基本操作;

  7. 输入输出重定向 - 了解标准输入、标准输出、标准错误;

  8. 管道 - 了解命令管道的组合应用;

  9. 常用命令 - 认识高频使用的Linux命令,练习基本使用;

  10. 内容搜索 - 练习搜索文件内容;

  11. 文件定位 - 增强文件检索能力;

  12. 软件包管理 - 练习安装卸载软件包,查看软件包信息等;

  13. 服务管理 - 关于服务管理的最佳实践。

1. 安装虚拟机

为方便练习,推荐使用虚拟机安装Linux。学会用最关键,以后再考虑在笔记本、PC或服务器等真机上安装Linux。

提到虚拟机软件,你可能听说过 VMware Workstation(下称 VM)。VM 功能丰富又强大,自然价格不便宜。

我不推荐使用 VM 的破解版,可能出现各种莫名问题,不稳定,捆绑软件甚至病毒。同时,作为IT行业的(可能)从业者,希望你一样尊重作者的版权。

VirtualBox (下称 VBOX)是一款免费、简单好用、稳定的虚拟机软件,用过的人都说好。

关于Linux发行版,我们选择红帽系、免费、稳定好用的CentOS。为什么不选择Ubuntu?因为,多数企业选择红帽或CentOS。

本教程将使用VBOX和CentOS,让你快速学会Linux基本使用。

VBOX依赖CPU的虚拟化支持,否则会提示“虚拟化未开启”之类的错误。

笔记本或台式机通常默认开启了CPU虚拟化支持。
品牌办公机、迷你一体机(苹果除外)之类的电脑由于成本问题,可能CPU不支持虚拟化技术。

怎么启用CPU虚拟化?

请在开机界面按特殊按键,进入BOIS设置。
具体设置步骤各不相同,请在搜索引擎搜索关键字,比如“Thinkpad E495 CPU 启用 虚拟化”、“神舟 战神 CPU 启用 虚拟化”。

1.1. 下载软件

请选择速度快的下载地址

1.1.2. CentOS7镜像文件

访问下载服务器地址,找到安装光盘的ISO文件,下载之。

建议下载迷你版安装光盘,文件名带 Minimal 字样。

如,"CentOS-7-x86_64-Minimal-2009.iso"

阿里云镜像服务器地址

https://mirrors.aliyun.com/centos/7/isos/x86_64/

网易镜像服务器地址

https://mirrors.163.com/centos/7/isos/x86_64/

1.2. VirtualBox介绍

VirtualBox官网

https://www.virtualbox.org/

VirtualBox是一款强大的x86和AMD64/Intel64虚拟化产品,适用于企业和个人。作为通用的x86硬件全虚拟化器,志在服务器、桌面和嵌入式领域。

VirtualBox有极其丰富的功能和高性能以满足企业客户,同时也是唯一一款使用GPL协议开源的虚拟机软件,无需购买即可使用所有(高级)功能

当前,VM可以运行在以下系统上:

Windows hosts (64-bit)
  • Windows 8.1

  • Windows 10 RTM (1507 / 2015 LTSB) build 10240

  • Windows 10 Anniversary Update (1607 / 2016 LTSB) build 14393

  • Windows 10 Fall Creators Update (1709) build 16299

  • Windows 10 April 2018 Update (1803) build 17134

  • Windows 10 October 2018 Update (1809 / 2019 LTSC) build 17763

  • Windows 10 May 2019 Update (19H1 / 1903) build 18362

  • Windows 10 November 2019 Update (19H2 / 1909) build 18363

  • Windows Server 2012

  • Windows Server 2012 R2

  • Windows Server 2016

  • Windows Server 2019

Mac OS X hosts (64-bit)
  • 10.13 (High Sierra)

  • 10.14 (Mojave)

  • 10.15 (Catalina)

Linux hosts (64-bit). Includes the following
  • Ubuntu 18.04 LTS, 19.03 and 19.10

  • Debian GNU/Linux 9 ("Stretch") and 10 ("Buster")

  • Oracle Linux 6, 7 and 8

  • Red Hat Enterprise Linux 6, 7 and 8

  • Fedora 30 and 31

  • Gentoo Linux

  • SUSE Linux Enterprise server 12 and 15

  • openSUSE Leap 15.1

随着VirtualBox活跃的开发,更快的版本更新,支持的系统和平台越来越多,越来越多的用户选择了它。

1.3. 在Windows上安装VirtualBox

1.3.1. 安装VirtualBox

  1. 找到刚才下载的 VBOX 安装包并双击运行

安装VirtualBox-1
  1. 单击安装界面的 “下一步”

安装VirtualBox-2
  1. 根据需要修改安装路径,建议保持默认不修改。然后单击 “下一步”

安装VirtualBox-3
  1. 保持默认勾选,直接单击 “下一步”

安装VirtualBox-4
  1. 单击 “是” 安装 VBOX 的网络功能

安装VirtualBox-5
  1. 直接单击 “安装”

安装VirtualBox-6
  1. 自动安装过程一

安装VirtualBox-7
  1. 自动安装过程二

安装VirtualBox-8
  1. 自动安装过程三

安装VirtualBox-9
  1. 自动安装过程四

安装VirtualBox-10
  1. 自动安装过程五

安装VirtualBox-11
  1. 直接单击 “完成”

安装VirtualBox-12
  1. 安装成功后,会自动运行 VBOX 软件,如下图所示:

安装VirtualBox-13

1.3.2. 安装VirtualBox扩展包

VBOX 的高级功能依赖于扩展包,包括 USB 2.0 和 USB 3.0 设备,VirtualBox 远程桌面,硬盘加密,NVMe(M2)固态硬盘等。

  1. 双击运行扩展包安装程序

安装VirtualBox-14
  1. 单击弹出窗口上的 “安装”

安装VirtualBox-15
  1. 拖动许可协议窗口右边滚动栏,拉到底部(重要!!!!!!)

安装VirtualBox-16
  1. 拉到底部之后,灰色不可用的 “我同意” 按钮变为可点击。然后,单击 “我同意”

安装VirtualBox-17
  1. 一切顺利的话,很快就能看到成功安装的提示框

安装VirtualBox-18

至此,VBOX 基础软件和扩展包已经安装完毕。

1.4. 创建第一个虚拟机

我前面提过,本教程使用 CentOS7(Linux发行版)作为系统平台。

根据下面的提示创建第一个(CentOS7)虚拟机。

1.4.1. 创建虚拟机

  1. 打开 VBOX 软件,在界面上单击 “新建” 按钮

创建第一个虚拟机-1
  1. 修改 “新建虚拟电脑” 中的 “名称”,这里我以 “CentOS7” 为例。至于 “文件夹”,建议新手默认,高级用户随意。其它设置保持默认,新手请勿修改。

创建第一个虚拟机-2
  1. 出于个人习惯,我将 “文件夹” 指定到了 D

创建第一个虚拟机-3
  1. 同样根据个人需要自行修改 vdi 文件位置,新手默认。第一个虚拟机 “文件大小” 直接默认8G就虚拟机文件行,其余全部默认。然后,单击 “创建”

创建第一个虚拟机-4
  1. 创建完成

创建第一个虚拟机-4-0

1.4.2. 设置虚拟机

根据教程内容,你需要设置光驱加载ISO文件和桥接网卡。

  1. 注意下图中的 “[光驱] 没有盘片” 和 “网络地址转换(NAT)” ,单击 “设置”

创建第一个虚拟机-5
  1. 弹出默认虚拟机设置

创建第一个虚拟机-6
  1. 找到 “存储” 中的 “控制器:IDE”

创建第一个虚拟机-7
  1. 单击 “分配光驱” 后面的光盘图标

创建第一个虚拟机-8
  1. 选择 “Choose a disk file…​”

创建第一个虚拟机-9
  1. 找到提前下载好的ISO文件并单击,然后单击 “打开”

创建第一个虚拟机-10
  1. 设置效果,如图所示:

创建第一个虚拟机-11
  1. 不过,我们还需要修改开机启动顺序,设置为开机光驱启动。选择 “第一IDE控制器主通道”

创建第一个虚拟机-12
  1. 最终设置,如下图所示:

创建第一个虚拟机-13
  1. 接下来设置网卡,单击左侧的 “网络”

创建第一个虚拟机-14
  1. 单击 “连接方式(A)”

创建第一个虚拟机-15
  1. 选择列表中的第二个,即 “桥接网卡”

创建第一个虚拟机-16
  1. 界面名称保持默认,不要改动。否则可能导致网络不同。

创建第一个虚拟机-17
  1. 设置完毕,如图所示:

创建第一个虚拟机-18
  1. 单击 “OK”,回到软件主界面,光驱和网卡对应的文字已经发生变化。

创建第一个虚拟机-19

1.5. 在虚拟机中安装CentOS(上)

通常,
我说的 “单击” 是指点击鼠标左键 icon mouse left click
我说的 “右击” 是指点击鼠标右键 icon mouse right click

1.5.1. 开始

鼠标左键 icon mouse left click

单击虚拟机屏幕中的任何地方后,鼠标和键盘会被虚拟机捕获。之后,鼠标和键盘输入将对虚拟机有效,方便在虚拟机中输入文字等。不要紧张,你不是对它们失去了控制!

键盘右侧 Ctrl

鼠标键盘被捕获后,输入操作已经完成,用来退出虚拟机屏幕。按一下,会看到鼠标恢复正常控制。

  1. 打开 VBOX 软件界面,选中左侧的 “CentOS7” ,然后单击 “启动”

在虚拟机中安装CentOS(上)-1
  1. 虚拟机 “电源” 通电后,你会看到如下界面

在虚拟机中安装CentOS(上)-2
  1. icon mouse left click 单击右上角的蓝色 ch01.s5 3 close ,关闭提示

在虚拟机中安装CentOS(上)-3
  1. 关闭提示后,如图所示:

在虚拟机中安装CentOS(上)-4
  1. icon mouse left click 单击黑色背景区域,让鼠标被虚拟机捕获。这时,你可以使用键盘 箭头选择菜单中的 “Install CentOS 7”

在虚拟机中安装CentOS(上)-5
  1. Enter,启动安装过程

在虚拟机中安装CentOS(上)-6
  1. 等待启动完成,通常需要20秒左右

在虚拟机中安装CentOS(上)-7

1.5.2. 安装(上)—— 基本参数设置

鼠标左键 icon mouse left click

单击虚拟机屏幕中的任何地方后,鼠标和键盘会被虚拟机捕获。之后,鼠标和键盘输入将对虚拟机有效,方便在虚拟机中输入文字等。不要紧张,你不是对它们失去了控制!

键盘右侧 Ctrl

鼠标键盘被捕获后,输入操作已经完成,用来退出虚拟机屏幕。按一下,会看到鼠标恢复正常控制。

  1. CentOS 7 安装界面——欢迎界面

在虚拟机中安装CentOS(上)-8
  1. icon mouse left click 单击右上角的蓝色 ch01.s5 3 close ,关闭提示

在虚拟机中安装CentOS(上)-9
  1. 单击虚拟机屏幕,输入英文 “chinese” ,正上方会出现你要找的 “中文”

在虚拟机中安装CentOS(上)-10
  1. 选择 “中文” → “简体中文(中国)” ,然后单击 “继续”

在虚拟机中安装CentOS(上)-11
  1. CentOS 7 安装界面——安装信息摘要。稍等一会儿,下方灰色区域会变为可操作

在虚拟机中安装CentOS(上)-12
  1. 如图所示:

在虚拟机中安装CentOS(上)-13
  1. 向下拖动右边 隐藏 的滚动条,或使用鼠标滚轮向下拖动

在虚拟机中安装CentOS(上)-14
  1. 找到 “系统” → “安装位置”

问:为什么不使用自动分区?

答:
自动分区确实方便。安装程序默认会使用LVM创建卷,系统会安装在卷上。
以后你有可能学习硬盘分区或文件系统相关知识,LVM会引入不必要的复杂度,越学越蒙。
见过很多头铁不听忠告的,遇到问题要么学LVM要么手动分区。

如果你能hold住,欢迎尝试LVM。

1.5.3. 安装(上)—— 设置分区

鼠标左键 icon mouse left click

单击虚拟机屏幕中的任何地方后,鼠标和键盘会被虚拟机捕获。之后,鼠标和键盘输入将对虚拟机有效,方便在虚拟机中输入文字等。不要紧张,你不是对它们失去了控制!

键盘右侧 Ctrl

鼠标键盘被捕获后,输入操作已经完成,用来退出虚拟机屏幕。按一下,会看到鼠标恢复正常控制。

在虚拟机中安装CentOS(上)-15
  1. 单击 “安装位置”

在虚拟机中安装CentOS(上)-16
  1. “设备选择” 能看到之前配置的8G硬盘,保持勾选状态。

在虚拟机中安装CentOS(上)-17
  1. 单击 “我要配置分区”

在虚拟机中安装CentOS(上)-18
  1. 然后,单击 “完成” 按钮

在虚拟机中安装CentOS(上)-19
  1. 会自动弹出 “手动分区” 界面

在虚拟机中安装CentOS(上)-20
  1. 单击 “新挂载点将使用以下分区方案” 下的列表,选择 “标准分区”

在虚拟机中安装CentOS(上)-21
  1. 然后,单击上方的 “点这里自动创建他们”

在虚拟机中安装CentOS(上)-22
  1. 系统帮助你创建的分区如下:

在虚拟机中安装CentOS(上)-23
  1. 这里没什么要修改,直接单击 “完成”

在虚拟机中安装CentOS(上)-24
  1. 弹出 “更改摘要”

在虚拟机中安装CentOS(上)-25
  1. 选择 “接受更改”

在虚拟机中安装CentOS(上)-26

1.5.4. 安装(上)—— 网络设置

鼠标左键 icon mouse left click

单击虚拟机屏幕中的任何地方后,鼠标和键盘会被虚拟机捕获。之后,鼠标和键盘输入将对虚拟机有效,方便在虚拟机中输入文字等。不要紧张,你不是对它们失去了控制!

键盘右侧 Ctrl

鼠标键盘被捕获后,输入操作已经完成,用来退出虚拟机屏幕。按一下,会看到鼠标恢复正常控制。

  1. 分区设置完毕,又回到了欢迎界面。然后,单击 “网络和主机名” ,设置网络参数

在虚拟机中安装CentOS(上)-27
  1. 如图所示:

在虚拟机中安装CentOS(上)-28
  1. 将右边的网络开关按钮切换至 “打开” 。网络如果正常,旁边会显示IP地址信息。

在虚拟机中安装CentOS(上)-29
  1. 至于主机名看个人心情设置

主机名只能使用英文字母、数字、下划线和点,长度不能超过30个字符
在虚拟机中安装CentOS(上)-30
  1. 网络参数设置完毕,单击 “完成”

在虚拟机中安装CentOS(上)-31
  1. 回到欢迎界面,可以看到网络已经连接

在虚拟机中安装CentOS(上)-32

1.6. 在虚拟机中安装CentOS(下)

  1. 所有安装参数已经设置完毕,单击 “开始安装” 继续安装

在虚拟机中安装CentOS(下)-1
  1. 安装进行中,这时单击 “ROOT 密码” ,设置 root 用户密码

在虚拟机中安装CentOS(下)-2
  1. 第一次装虚拟机密码请尽量简单,方便记忆

在虚拟机中安装CentOS(下)-3
  1. 比如,你可以设置为 12345678

云服务器、云数据库等任何连接到互联网的系统或服务,请保证密码足够安全。123456admin 等这种密码是绝对不安全的。
在虚拟机中安装CentOS(下)-4
  1. 第二次输入密码

在虚拟机中安装CentOS(下)-5
  1. 单击 “完成” 。如果你的密码少于六位数,必须 单击两次 才能设置成功,可以忽略 黄色警告 提示

在虚拟机中安装CentOS(下)-6
  1. 安装进行中

在虚拟机中安装CentOS(下)-7
  1. 安装进行中

在虚拟机中安装CentOS(下)-8
  1. 安装完成

在虚拟机中安装CentOS(下)-9
  1. 单击 “重启” 按钮

“重启” 操作只对虚拟机有效,不会重启你的 Windows。
在虚拟机中安装CentOS(下)-10

1.7. 启动CentOS

  1. 执行重启后,虚拟机会忽略之前设置的光驱启动,直接从刚才安装的 “CentOS7” 启动

启动CentOS-1
  1. 启动完成,进入登录界面

启动CentOS-2
  1. 单击虚拟机屏幕,进入虚拟机并输入用户名 root,密码 12345678,然后按 Enter。如果登录失败,会再次提示输入用户名和密码。

输入密码时,为了安全,系统不会在屏幕上显示密码或星号。不要为 “Password” 后面不显示而困扰。
启动CentOS-3
  1. 进入系统后,执行命令 ip a 查看IP地址(192.168.2.236)。请记住这个地址,下一章你需要使用客户端工具,通过网络连接CentOS7。

启动CentOS-4

2. 客户端工具

你需要了解这些
  • 通常支持客户端工具的工具,我们统称为 客户端工具

  • Linux(如之前安装的 CentOS 7)上自带客户端工具(Linux终端)。

2.1. 客户端工具介绍

2.1.1. 图形界面工具

Linux社区有许多免费的图形化连接工具,足够日常使用,不需要使用收费软件,也没必要使用破解软件。比如Xshell、SecureCRT等。
Putty(开源)

迷你版的连接工具,欠缺方便的标签管理功能,每次连接远程主机比较麻烦。

不推荐作为主力工具使用。

MobaXterm(免费版)

强烈推荐Windows用户使用

主要特性
  • 支持Linux(SSH)、telnet、VNC、Windows(RDP)连接;

  • 支持X11-Forwarding;

  • 自动SFTP浏览支持;

  • 最多保存12个服务器标签(session);

  • 最多同时建立两个连接隧道。

2.1.2. 命令行工具

WSL终端

WSL是Windows 10上的迷你Ubuntu系统,能够运行几乎所有Linux命令,没有图形界面。可以把WSL看做运行在Windows 10系统下的Linux终端。

如果你使用Windows 10做主力系统,又能接受没图形界面,请移步 客户端工具之Linux终端

Linux终端

Linux系统自带的命令行工具,配合 ssh 命令连接远程主机非常方便。

如果你使用Linux做主力系统,请移步 客户端工具之Linux终端

2.1.3. 最后

现在,我开始介绍Windows下好用、功能丰富又免费的MobaXterm。

2.2. MobaXterm安装

2.2.2. 安装

解压下载的文件 MobaXterm_Installer_v12.4.zip,双击运行解压后的 MobaXterm_Installer_v12.4.msi

ch02.s2-1

MobaXterm和大多数Windows软件一样,都使用安装向导。当你准备好之后,单击 Next 按钮。

ch02.s2-2

同意软件用户协议,勾选 " I accept the terms in the License Agreement" ,继续安装。

ch02.s2-3

软件安装位置,保持默认即可。

ch02.s2-4

单击 Install 开始安装。

ch02.s2-5

MobaXterm安装完成。

ch02.s2-6

2.2.3. 运行

安装后,可以在开始菜单中找到MobaXterm。

ch02.s2-7

桌面上也有MobaXterm快捷方式,双击MobaXterm图标,运行看看。

ch02.s2-8

2.2.4. 最后

你也看见了,MobaXterm启动后是英文界面。

可能有人正在百度搜索 "MobaXterm中文破解版""MobaXterm中文绿色版"

MobaXterm不支持中文 ,你也不需要中文,不要高估自己的需求。

照猫画虎,跟着我学会日常使用。

2.3. MobaXterm连接远程主机

MobaXterm把连接称为Session,每个连接对应一个Session,在Session中可以配置连接参数(IP地址、端口、帐号、密码、私钥等)。

"连接" 在这里是名词,表示从你电脑到远程主机之间的一个网络连接。连接是你和远程主机的一个通道,通道拥有地址(IP地址)、车道(端口)、车牌号(帐号)等等属性。

单击 Session 按钮,创建一个连接。

ch02.s3-1

选择 SSH 按钮。

ch02.s3-2

这时,你可以看到 "Basic SSH settings" 标签,包含连接的基本信息。

功能说明
Remote Host

远程主机IP地址

Specify username

用户名

Port

端口

ch02.s3-3

"Remote Host" 中输入远程主机IP地址(192.168.2.236)。

不知道自己虚拟机IP地址?

请参考“准备VirtualBox虚拟机”→“1.7. 启动CentOS”查看远程主机IP地址。

ch02.s3-4

勾选 " Specify username"

ch02.s3-5

输入用户名:root,单击 OK 按钮连接远程主机。

ch02.s3-6

在黑色窗口中,输入远程主机密码,然后按 Enter 键。

输入密码时,屏幕上不会显示密码。
ch02.s3-7

MobaXterm会提示是否保存远程主机密码。勾选 " Do not show this message again",按 Yes 按钮保存密码。

ch02.s3-8

一切顺利的话,你可以看到下面这样的提示信息。

ch02.s3-9

也许你好奇左边的目录是什么?

下一小节会介绍简单使用,更多的会在第三章中介绍。

2.4. MobaXterm设置无密码登录

2.4.1. 选择?

MobaXterm有记住密码功能,连接远程主机不会提示密码,使用方便。

这对大多数人来说已经足够,对无密码登录(密钥登录)没有需要,请跳过本节内容。

如果你有以下情况,建议开始阅读以下内容:

  • 远程主机未开启密码登录支持,仅支持密钥登录;

  • 可能存在多终端设备(如Windows、Mac、手机等)连接远程主机的情况;

  • 重视个人隐私,不希望有软件记录远程主机密码。

我笔记本的主力系统是Archlinux,写文案偶尔会切换到Windows系统。外出使用安卓手机的 JuiceSSH 终端。没有密钥登录,我简直寸步难行。想想远程主机的超长随机密码…​…​
本节操作步骤较多,慢慢操作,不要 "迷路"

2.4.2. 密钥对介绍

密码不方便记忆,有时候为了安全设置长密码让问题更凸显,也有时候是因为远程主机太多。

我个人的习惯是第一次登录之后立刻设置无密码登录,业内大家更喜欢称为密钥登录。

如果你是第一次使用无密码登录,需要生成密钥对。密钥对生成后,可以重复使用,不需要每次生成。我的远程主机使用密钥对已经超过十年。

如果你有密钥对,直接上传公钥(锁)到远程主机,使用私钥(钥匙)可以登录远程主机。不用再生成密钥对。

在开始之前,需要说明一下。

密钥对包括两个文件:私钥文件(Private Key),公钥文件(Public Key)。

私钥文件

相当于门钥匙,作为登录远程主机的关键。

公钥文件

相当于门锁,只要有钥匙就可以打开。公钥文件可以发布到任何地方,不需要保密。

私钥文件不能外泄,否则远程主机有严重的安全风险。

2.4.3. 生成密钥对

生成密钥对

MobaXterm的 "Tools" 中包含很多实用工具,也包含了密钥生成工具。

单击 Tools  MobaKeyGen(SSH key generator),打开操作界面。

ch02.s4-1

单击 Generate 按钮,开始生成密钥对。

ch02.s4-2

移动鼠标可以产生更多随机数,从而加速过程。

ch02.s4-3

生成需要约一分钟。

ch02.s4-4

密钥对生成完毕。

ch02.s4-5
准备工作

新建名为 "ProLinux" 的文件夹,用来保存公钥文件和私钥文件。

如,我在 D: 盘新建文件夹 "ProLinux"

ch02.s4-7
ch02.s4-8
如何新建文件夹? 鼠标右键  新建(W)  文件夹(F)

最终,我的文件夹绝对路径为:

"D:\ProLinux"

保存公钥

配置无密码登录不能直接用 Save public key 功能保存公钥,必须直接复制公钥内容才行。

ch02.s4-6

具体操作见下文。

复制下图文本框中的所有内容:

ch02.s4-6-1

双击进入 "ProLinux" 文件夹 → 新建一个 "文本文档" → 文件名设置为 "mk.pub"

ch02.s4-9
怎样新建文本文档? 在 "mk.pub" 文件上,单击 鼠标右键  新建(W)  文本文档

最后,用记事本打开 "mk.pub" 文件 → 粘贴公钥内容 → 按 Ctrl+S 保存:

ch02.s4-9
怎样用记事本打开? 鼠标右键  打开方式  记事本
保存私钥

单击 Save private key 按钮,开始保存 私钥文件 操作。

ch02.s4-10

未设置私钥密码,MobaXterm会弹出警告,选择 是(Y) 忽略之。

私钥密码相当于再给锁上加锁,更安全。即便遗失,也不用担心。连接远程主机时,必须输入密码才能使用私钥。
普通人不需要这样的安全等级,不需要设置私钥密码。
ch02.s4-11

进入刚才创建的 "ProLinux" 文件夹,在 "文件名(N):" 中填写私钥文件名,此处以 mk 为例。单击 保存(S) 按钮,保存文件。

保存类型(T) 默认是 "*.ppk",最终私钥文件名为 "mk.ppk"
ch02.s4-12
查看密钥文件

按照步骤操作完毕后,会得到两个文件:

mk.pub

公钥文件,必须上传到远程主机(详情见下一小节)。

mk.ppk

私钥文件,在MobaXterm的Session属性中启用之后,连接远程主机生效(详情见下一小节)。

ch02.s4-13

2.4.4. 上传公钥

为降低难度,不打算让你 编辑文件,不管是 本地 还是 远程主机 上。

在准备好配置文件之后,让你用鼠标操作完成设置,简单直接。

设置完成后,在远程主机上的 ~/.ssh/authorized_keys 文件中会包含你的公钥。

准备authorized_keys文件

选中 "mk.pub"Ctrl+C 复制文件。

ch02.s4-14

然后,直接按 Ctrl+V 粘贴文件,如图中的 "mk - 副本.pub"

ch02.s4-15

选中文件 "mk - 副本.pub",按 F2 重命名文件名为 "authorized_keys"

双击浏览器中的文字会直接选中,按 Ctrl+C 复制即可,比如上面的 "authorized_keys"
ch02.s4-16

接着你会看见下面这个提示,选择 是(Y)

ch02.s4-17

配置文件准备好了。

ch02.s4-18
上传公钥

双击 User sessions  192.168.2.236(root) 连接远程主机。

ch02.s4-19

下图左边的内容被称为目录树,可以用鼠标操作或编辑文件。
单击 "/root/" 上方中间的黄色 图标,

ch02.s4-20

创建名为 ".ssh" 的隐藏文件夹。

Linux系统中,以点 "." 开头的文件或文件夹均为隐藏文件。 ls 命令查看时,需要带参数 a,这样:ls -a
ch02.s4-21

结果如图所示,然后双击进入 ".ssh" 文件夹。

ch02.s4-22

接着单击浅蓝色向上箭头 图标上传文件。

ch02.s4-23

在弹出的选择框中,找到 "Prolinux" 文件夹下的 "authorized_keys" 文件,双击选择。

ch02.s4-240

上传成功后,在目录树中会看到 "authorized_keys"

ch02.s4-25
先不要关闭连接标签,接着配置SELinux。
关闭SELinux
SELinux功能过于复杂,关闭之是最好选择。否则,无密码登录将会失败。

在已经打开的连接标签中,复制下面三条命令,粘贴到黑色窗口中,然后敲回车执行:

echo SELINUX=disabled>/etc/selinux/config
echo SELINUXTYPE=targeted>>/etc/selinux/config

reboot

执行成功后,CentOS系统会被重启。等待重启成功后,可以继续后面的操作。

2.4.5. 启用私钥

选择 User sessions  192.168.2.236(root)  Edit session 编辑远程主机配置参数。

ch02.s4-27

弹出设置界面:

ch02.s4-28

选择 "Advanced SSH settings" 标签,找到 "User private key" 参数,单击输入框尾部的文件 图标。

ch02.s4-29

弹出文件选择框,双击私钥文件 "mk.ppk"

ch02.s4-30

设置效果如图所示,单击 OK 保存配置。

ch02.s4-31

2.4.6. 测试无密码登录

启用私钥后,必须关闭连接。重新连接远程主机,才能确认私钥是否有效。

在MobaXterm主界面双击 User sessions  192.168.2.236(root),测试连接远程主机。

ch02.s4-32

如果登录成功,说明密钥设置没问题。

ch02.s4-33

3. 传输文件

本章内容是为有传输文件需求的你准备的,可以先跳过。等你准备好时,再来实践学习。

打开你的MobaXterm,连接上远程主机,开始练习…​…​

3.1. 用MobaXterm上传下载文件

3.1.1. 准备文件

为减少操作步骤,我会使用 Windows终端 简称(终端)创建文件。

打开Windows终端

在文件资源管理器中打开 D:\ProLinux,单击地址栏:

ch03.s1-1

输入 "cmd",按 Enter 键。

ch03.s1-2

Windows终端 如下图所示:

ch03.s1-3
创建文件
创建目录和文件相关操作都在终端中完成。
  • 在终端中创建目录,名称为 "files"

mkdir files
  • 在目录 "files" 下创建名为 "foo.txt" 的文件,文件内容为 "test text: foo"

echo 'test text: foo' > files/foo.txt
ch03.s1-11
  • 同样的方式创建 "bar.txt"

echo 'test text: bar' > files/bar.txt
ch03.s1-12
  • 查看目录 "files" 下的文件,确认是否创建成功:

dir files
ch03.s1-13
Figure 1. 操作演示
D:\ProLinux>dir files
 驱动器 D 中的卷没有标签。
 卷的序列号是 B4E5-398C

 D:\ProLinux\files 的目录

2020/02/26  17:18    <DIR>          .
2020/02/26  17:16    <DIR>          ..
2020/02/26  17:18                19 bar.txt
2020/02/26  17:17                19 foo.txt
               2 个文件             38 字节
               2 个目录 240,456,257,536 可用字节
  • 关闭终端

  • 在文件资源管理器中查看:

ch03.s1-4
ch03.s1-5

3.1.2. 上传文件或目录

登录远程主机之后,直接(按住左键)将 "files" 目录拖拽到MobaXterm左边的目录树:

ch03.s1-6
确认上传
  • 方法一:MobaXterm目录树

ch03.s1-7
ch03.s1-8
  • 方法二:Linux命令

    • 查看 "files" 目录:

ls -l ~
操作演示
[root@prolinux ~]# ls -l
total 4
-rw-------. 1 root root 1305 Dec  7 16:31 anaconda-ks.cfg
drwxr-xr-x. 2 root root   36 Feb 26 17:42 files
  • 查看 "files" 目录下的文件:

ls -l files/
操作演示
[root@prolinux ~]# ls -l files/
total 8
-rw-r--r--. 1 root root 19 Feb 26 17:42 bar.txt
-rw-r--r--. 1 root root 19 Feb 26 17:42 foo.txt

屏幕截图:

ch03.s1-9

3.1.3. 下载文件或目录

下载和上传方法都是一样的,直接把MobaXterm目录树中显示的文件或目录拖拽到本地就行了。

上传

MobaXterm目录树 Windows文件资源管理器

下载

Windows文件资源管理器 MobaXterm目录树

4. 文件、目录与路径

本章使用Gnome桌面+Linux终端完成演示效果

4.1. 什么是文件

Linux以文件的形式储存数据,常见的文件有图片、Word文档、PPT、PDF等等。

常以名称、大小来描述一个文件。

如下图所示:

ch04.s1-1
ch04.s1-1.1

4.1.1. 文件名称

ch04.s1-2
ch04.s1-2.1

上图的 "pic10"名称".jpg"扩展名 ,合在一起就是完整的文件名称 "pic10.jpg"

什么是文件名称?
呃呃呃…​就是一个名字(dog脸)。

为什么你知道 "pic10.jpg" 是一个图片文件,"book.pdf" 是一个PDF文件?
还不是因为扩展名。

那在Linux中扩展名有什么用呢?
小声告诉你~
其实没用,只为好看而已。

在Windows中,文件扩展名决定了Windows会用哪个软件打开。

最后要强调一下:

文件名称甚至扩展名只是一个名字,文件名称不影响文件内容或文件类型。

4.1.2. 文件大小

ch04.s1-3
ch04.s1-3.1

上面这个截图说,"pic10.jpg" 文件大小为 "72.3KB""72,322 字节"

文件大小的基本度量单位是 byte(字节)。

大文件用字节表示时太长,可以用千字节(KiB/kB)、兆(MiB/MB)、吉(GiB/GB)、太(Tib/TB)来表示。

“为什么有Kib,又有KB?有什么不同?”
“因为采用的度量标准不同,Kib是用2的整数次幂计算(二进制乘数词头标准),kB是用10的整数次幂计算(国际单位制词头标准)。” “全部用byte(字节)表示就没这个问题(机智),就是太长(微笑)。”


举栗子,

“1. 我要换个头像,这张200kB的看起还将就~”

200kB = 200千字节 = 200 * 10的3次方字节 = 200000byte

“2. 新买的手机拍照效果很好,照片分辨率2592x3840,每张大概4MB、5MB的样子。”

4MB = 4兆 = 4 * 10的6次方字节 = 4000000byte

“3. 下了部加长版的阿凡达,1080P版本的,有42.5GB大。”

42.5GB = 42.5吉 = 42.5 * 10的9次方字节 = 42500000000byte

“4. 买了个2TB的希捷硬盘,用来放实验数据。”

2TB = 2太 = 2 * 10的12次方字节 = 2000000000000byte

“5. 在Linux终端下,用 『du -sh』命令统计Downloads目录下有15GiB的文件。”

15GiB = 15吉 = 15 * 2的30次方字节 = 16106127360byte


是不是已经凌乱了?确实,Linux、Windows、Mac以及各种软件都没有统一的度量标准这点让人头痛。

另外一个常见栗子:

“买了2T的硬盘,插到电脑上,只显示1.8T。奸商~”

“到底硬盘厂家是不是奸商呢?”
“因为计算容量的标准不同,硬盘厂家用10的整数次幂计算,你的电脑用的2的整数次幂计算。所以,硬盘容量最终是有差距。”


为了美好的生活,你只需要记住:

Windows、Linux终端使用二进制乘数词头计算文件大小,Linux桌面软件(比如,Gnome)、硬盘厂家则使用国际单位制词头。

如果你想成为优秀的程序员,那一定要搞清楚:MiBMB 有什么区别?
去维基百科看看 二进制乘数词头国际单位制词头 是不错的选择。

4.1.3. 空文件

大小为0或没内容的文件,称作 空文件

4.2. 什么是目录(文件夹)

目录相当于一个容器,将多个文件或其它目录存储在一起。

Linux系统包含成千上万个目录。

多个文件通过存储在一个目录中,可以达到有组织的存储文件的目的。

在一个目录中的另一个目录被称作它的子目录(子文件夹)。这样,这些目录就构成了树状网络,或目录树。


ch04.s2-1

上面这个目录树有5个子目录和34个文件。

4.2.1. 目录还是文件?

在桌面中,你一眼就分辨出目录和文件了对吗?

ch04.s2-2

那现在呢?

ch04.s2-3

“这题我会~”

蓝色 的是目录,白色 的是文件。”

“ohhhhh~”

友情提示,

换个直观的办法:

ch04.s2-4

看到第一二行的第一列没,都是 drwxrwxr-x.。第一个字母 d 是英文directory的缩写,有它出现的地方就是目录啦~

那文件呢? -(中横线)开头的就是文件。

其实,我也是经常用颜色区分的,主要还是方便~哈哈
关于目录名称的迷惑

我创建了一个目录 "pic123456.jpg"。它是这个样子:

ch04.s2-5

“没问题呀!”

那这样呢?

ch04.s2-6

“看起来像图片文件对不对?”
“它…​还是目录哦~”

和之前一样,用 颜色 或者字母 d 可以分辨出来。

4.2.2. 空目录

目录下没有文件或子目录,同样称作 空目录

4.3. 什么是路径

路径表示文件或目录在Linux系统的位置,就像经纬度能够标示地球上的任何一个位置一样,防迷路。

各种路径:

  • /home/mk/Downloads/templated-radius/

  • /usr/share/zoneinfo/

  • /var/log/

  • /usr/share/zoneinfo/Asia/Shanghai

  • ../zoneinfo/Asia/Shanghai

  • /home/mk/Downloads/templated-radius/images/pic10.jpg

  • images/pic10.jpg

  • /home/mk/Downloads/templated-radius/assets/css/main.css

  • assets/css/main.css

  • ../../assets/css/main.css

路径以斜线(/)分隔,以文件名称或目录名称结尾。

我之前用树状结构(目录树)表示了文件和目录的关系。

现在,你会发现路径看起来像一条直线,更加直接。


为更精确表达,路径以文件名称结尾,称作文件路径。反之称作目录(文件夹)路径。

路径以斜线结尾(如,/var/log/)的,一定是目录(文件夹)路径。


路径太长时,用起来不方便。

Linux又有绝对路径和相对路径之分。

绝对路径太长时,用相对路径代替很方便。

接下来两小节,会详细介绍绝对路径和相对路径。

喜欢编程的小伙伴,在路径问题上踩过不少坑。还没踩坑的话,一定要看看下面两个小节哦~

4.4. 绝对路径

绝对路径以根目录(/)开头,不会因当前位置(工作目录)而变化。

根目录(/)是什么?

根目录是所有路径的起点,相当于Windows系统的 "C:\" 盘。

绝对路径例子:

  • /home/mk/Downloads/templated-radius/ ← 目录

  • /usr/share/zoneinfo/ ← 目录

  • /var/log/ ← 目录

  • /usr/share/zoneinfo/Asia/Shanghai ← 文件

  • /home/mk/Downloads/templated-radius/images/pic10.jpg ← 文件

  • /home/mk/Downloads/templated-radius/assets/css/main.css ← 文件

无法确定是文件路径还是目录路径时,可以使用 ls -lfile 命令查看,比如 file /usr/share/zoneinfo/Asia/Shanghai

绝对路径组成示例:

ch04.s4-1

4.5. 相对路径

相对路径是以当前目录(工作目录)为前提,使用 简短的路径 代替 绝对路径

相对路径可能以 "./" 或 "../" 开头。一个点表示当前位置,连续两个点表示上级目录。当以 "./" 开头时,可以被省略。


由于当前目录随时在变化,可能导致文件或目录明明 存在,却 找不到 的情况。

建议:
在终端中手动操作文件或目录时使用相对路径,其它情况下使用绝对路径。

为什么手动操作时用相对路径呢? 因为打字少!

看看这两个绝对路径:

  • /usr/bin

  • /usr/bin/cat

用相对路径表示:

  • ../bin./binbinbin/

  • ./bin/catbin/cat./cat

相对路径是否有效,取决于工作目录。

下面我以命令行和树状网络为例,详细说明:什么是相对路径?

4.5.1. 绝对路径与相对路径的转换:命令行

连接远程主机,跟我做:

  • ../bin./binbinbin/

操作演示
[mk@archlinux ~]$ ls -dl /usr/bin
drwxr-xr-x 7 root root 135168  2月 24 10:07 /usr/bin

[mk@archlinux ~]$ cd /usr/include/
[mk@archlinux include]$ ls -dl ../bin
drwxr-xr-x 7 root root 135168  2月 24 10:07 ../bin

[mk@archlinux ~]$ cd /usr
[mk@archlinux usr]$ ls -dl ./bin
drwxr-xr-x 7 root root 135168  2月 24 10:07 ./bin

[mk@archlinux usr]$ ls -dl bin
drwxr-xr-x 7 root root 135168  2月 24 10:07 bin

[mk@archlinux usr]$ ls -dl bin/
drwxr-xr-x 7 root root 135168  2月 24 10:07 bin/
  • ./bin/catbin/cat./cat

操作演示
[mk@archlinux ~]$ ls -l /usr/bin/cat
-rwxr-xr-x 1 root root 39048 11月 12 19:00 /usr/bin/cat

[mk@archlinux ~]$ cd /usr/
[mk@archlinux usr]$ ls -l ./bin/cat
-rwxr-xr-x 1 root root 39048 11月 12 19:00 ./bin/cat

[mk@archlinux usr]$ ls -l bin/cat
-rwxr-xr-x 1 root root 39048 11月 12 19:00 bin/cat

[mk@archlinux usr]$ cd bin
[mk@archlinux bin]$ ls -l ./cat
-rwxr-xr-x 1 root root 39048 11月 12 19:00 ./cat

4.5.2. 绝对路径与相对路径的转换:树状网络

Diagram

工作目录:/usr/bin
绝对路径:/usr/bin/cat
相对路径:./cat

4.5.3. 树状网络、绝对路径及相对路径一览表

Diagram
Table 1. 路径一览表
工作目录:/usr/include/

绝对路径

相对路径

说明

/usr/include/

.(一个点)

绝对路径和当前目录(/usr/include)相同

/usr/include/pwd.h

./pwd.h 或者 pwd.h

当前目录(/usr/include)下的 pwd.h 文件

/usr/include/linux/nfc.h

./linux/nfc.h 或者 linux/nfc.h

当前目录(/usr/include)的子目录 linux 有文件 nfc.h

/usr/lib/

../lib/

上级目录 /usr 下的子目录 lib

4.5.4. 总结

通过上面的这么多例子相信你注意到了一个规律:如果文件路径没有以 / 开头,那它是相对路径。

以此类推,假如我有文件名为 my.png 的文件,执行命令:

ls my.png

那上面的 my.png 会被命令视作相对路径,等同于 ./my.png

另外一个规律:如果将文件名作为参数用在命令行或软件中时,会被当作文件(相对)路径。同理,目录名称做参数时,情况相同。

4.6. 关于文件那些事儿

  • 区分大小写

  • 不关心扩展名

  • 隐藏文件:以 "." 开头的文件或目录

4.6.1. Linux区分大小写

这非常重要,也是Linux萌新常见问题的来源。

比如,我用Linux搭建了网站,有网页文件 "home.html",访问网址为:

一般情况下,访问 http://www.xquickstartguide.com/prolinux/test/HOME.html 会看到 "网页无法找到" 的错误提示。

大写的 "HOME.html" 文件实际是不存在的。

在Windows系统中,就没有 "HOME.html" 这样的问题。因为,Windows系统不区分大小写。

就日常使用来说,在Linux系统中可以创建两个或多个名字相同的文件和目录,只要大小写字母是不同的就行。如,foo.txt、FOO.txt、foo.TXT是三个同名文件。在Windows系统中创建 foo.txt 之后,创建文件 FOO.txt 会提示错误。

4.6.2. Linux不关心扩展(名)

[什么是文件] 一节中提过扩展(名),也许你之前难以理解。从这里开始,扩展名将变得更加具体。

扩展(名)一般由2到4个字符组成,用来表示文件类型。以下是常见扩展:

foo.exe

执行文件或程序

foo.txt

文本文件

foo.png/bar.gif/quz.jpg

图片

在Windows系统中扩展(名)非常重要,系统以此检测是什么类型的文件。Linux系统实际上会忽略扩展名,通过查看文件内容确定文件类型。比如,我有一个图片文件 my.png。我把文件重命名为 my.txt 之后,Linux还是会将之看作图片文件。因此,有时候很难确定某个特定文件是什么类型的文件。幸好有 file 的命令,它可以帮助确定文件类型。

用法

file 文件路径

示例
$ file my.txt
my.txt: PNG image data, 4480 x 1440, 8-bit/color RGBA, non-interlaced
现在,你肯定已经知道 "my.txt""./my.txt" 的简单用法。在 <相对路径_总结> 内容中已经说过,命令行中指定一个文件或目录(如 "my.txt")时,实际上会被视作文件路径("./my.txt")。

4.6.3. 隐藏文件

隐藏文件

在Linux系统中,任何以 "."(点)开头的文件是隐藏文件。默认情况下,不显示。比如,

# ls -l ~
总用量 4
-rw-------. 1 root root 948 827 2019 anaconda-ks.cfg

ls 命令只看到一个名为 "anaconda-ks.cfg" 的文件。

使用 -a 参数再试一次呢?

# ls -al ~
总用量 52
dr-xr-x---.  4 root root 4096 8月  27 2019 .
dr-xr-xr-x. 17 root root 4096 8月  27 2019 ..
-rw-------.  1 root root  948 8月  27 2019 anaconda-ks.cfg
-rw-------.  1 root root 8403 8月  27 2019 .bash_history
-rw-r--r--.  1 root root   18 12月 29 2013 .bash_logout
-rw-r--r--.  1 root root  176 12月 29 2013 .bash_profile
-rw-r--r--.  1 root root  176 12月 29 2013 .bashrc
-rw-r--r--.  1 root root  100 12月 29 2013 .cshrc
drwxr-xr-x   4 root root   48 8月  27 2019 .kube
drwxr-----.  3 root root   18 8月  27 2019 .pki
-rw-r--r--.  1 root root  129 12月 29 2013 .tcshrc
-rw-------   1 root root 4243 8月  27 2019 .viminfo

好,这次用 ls -al 看到 "~"(/root) 目录下有很多以 "." 开头的文件(隐藏文件)。

隐藏目录

如果目录以 "." 开头就是隐藏目录。是不是很简单?

试一试创建一个隐藏目录:

mkdir ~/.test_dir

ls ~

ls -a

测试完,记得删除 ".test_dir" 目录:

rm -rf ~/.test_dir
隐藏文件用来做什么

在Linux系统中,大多数软件都有自己的配置文件或者目录。

通常,全局配置文件会放在 "/etc" 目录下,用 ls 直接可见。

用户配置文件则放在 "~"(用户家目录)下,都是隐藏文件,用 ls -a 才能看见。

家目录下的配置文件多数是软件自动创建,隐藏起来显得更清爽。

5. 文件和目录管理

在开始本章之前,你要明白一件事情:对于Linux系统来说,一切都是 "文件"。文本、目录、你的键盘和鼠标等等都是 "文件"。可能有些意外,不过这不影响什么。但,请记住这一点,因为它有助于理解Linux命令的行为。

本章有较多命令输入,请使用 Tab 键补全文件名,更方便。

怎么使用补全快捷键?

比如,你要执行命令 ls /usr,具体操作方法为:

输入 ls /u → 按 Tab 键,会自动补全为 ls /usr

如果有多个相同字母开头的文件名,Tab 键补连续按两下,操作方法:

  1. 输入 ls /l

  2. 按第一次 Tab 键,补全为 ls /lib

  3. 再按一次 Tab 键,屏幕上会出现 lib/ lib64/

  4. ls /lib 基础上,你继续输入 ls /lib6

  5. 再按一次 Tab 键,终端就会补全为 ls /lib64

Tab 键的动作,只要你需要可以按无数次,特别是在文件名特别长的时候。

5.1. 在目录之间切换

cd 命令:在目录之间切换

5.1.1. 基础用法

cd 目录路径
参数
--help

查看帮助信息

5.1.2. 常用路径符号

"."

当前目录

".."

上级目录

"~"

家目录,root用户家目录为 "/root",其它用户家目录在 "/home"

5.1.3. 操作演示

绝对路径
目录变化

"/root""/usr"

[root@prolinux ~]# cd /usr
[root@prolinux usr]#
相对路径
目录变化

"/usr""/usr/local/bin"

[root@prolinux usr]# cd local/bin
[root@prolinux bin]#

或者

[root@prolinux usr]# cd ./local/bin
[root@prolinux bin]#
当前目录
目录变化

"/usr/local/bin""/usr/local/bin"

[root@prolinux bin]# cd .
[root@prolinux bin]#

看见了吧?

"." 没什么用,忘掉最好~

上级目录
目录变化

"/usr/local/bin""/usr/local"

[root@prolinux bin]# cd ..
[root@prolinux local]#
家目录
目录变化

"/usr/local""/root"

[root@prolinux local]# cd ~
[root@prolinux ~]#

偷懒的写法是,不要 "~",直接 cdEnter,不加参数。

想试一试?

没问题…​

先随便切换一个目录,比如 "/usr/local"

[root@prolinux ~]# cd /usr/local
[root@prolinux local]#

然后:

[root@prolinux local]# cd
[root@prolinux ~]#

5.2. 创建文件

5.2.1. 文件

创建空文件

创建一个空文件,如果文件已经存在,则会修改文件最后一次更新时间:

touch foo.txt
touch 命令本来用于修改文件时间。只是修改过程中,如果文件不存在,它会创建一个空文件。你就是利用这个特点创建的文件。
创建带内容的文件

有时,在创建文件之前,脑子里已经确定了内容,可以这样:

echo "这是测试文本。" > foo.txt
如果 foo.txt 文件已经存在,上面的命令会清空文件内容哦!

如果 foo.txt 文件已经存在,使用两个连续的大于符号( >> )可以追加一行或多行到文件最后。

echo "这是测试文本1。" >> foo.txt
echo "这是测试文本2。" >> foo.txt

最终,foo.txt 内容是这样:

这是测试文本。
这是测试文本1。
这是测试文本2。

5.2.2. 目录

创建目录,如果目录已经存在会报错,不用管:

mkdir ProLinux

有时,你会创建这样的目录 ProLinux/files/2020_03_03。创建多级目录也很简单,加参数 -p 就行:

mkdir -p ProLinux/files/2020_03_03

如果父目录 ProLinux 不存在,也能创建成功。同理,files 目录不存在也行。也就是说,路径中的所有子目录如果不存在,都会被创建。

划重点,-p 参数要考(滑稽)。

相对路径 ProLinux/files/2020_03_03 实际上省略了前面的 "./",可以写成:

  • ./ProLinux/files/2020_03_03

  • ./ProLinux/files/2020_03_03/

5.3. 列表目录

5.3.1. 查看目录

每次在终端上操作,你都需要确认你在哪个位置(工作目录或当前目录),才不至于 迷路

刚好,pwd 命令可以帮到你:

操作演示
[root@prolinux ~]# pwd
/root

好的,你现在处于 /root 目录。执行 ls 命令,可以直接看到本目录下内容:

ls 命令不加参数时,会直接查看当前目录下的内容。
也可以使用 ls . 命令,前者只是省略了(相对)路径参数。
操作演示
[root@prolinux ~]# ls
files  ProLinux

[root@prolinux ~]# ls .
files  ProLinux

你要明白,上面的方法不是唯一的方法。也可以查看绝对路径下的目录内容:

ls /root/
操作演示
[root@prolinux ~]# ls /root/
files  ProLinux

ls .. 可以查看上级目录:

操作演示
[root@prolinux ~]# ls ..
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr

也可以指定更加复杂的相对路径:

ls ../usr/src/
操作演示
[root@prolinux ~]# ls ../usr/src/
debug  kernels

当然,也可以查看当前目录下的子目录内容:

ls files/
操作演示
[root@prolinux ~]# ls files/
bar.txt  foo.txt
查看隐藏文件

凡是以 . 开头的文件或目录,都称为隐藏文件或目录。配合 -a 参数可以看到:

操作演示
 [root@prolinux ~]# ls -a
.   .bash_history  .bash_profile  .cache   .cshrc  .lesshst  ProLinux  .tcshrc
..  .bash_logout   .bashrc        .config  files   .pki      .ssh      .viminfo

5.3.2. 列出更多信息

有时,你需要知道文件的修改时间或者权限。ls -lll 命令会以列表的方式,将文件信息打印到屏幕上。

llls -l 的命令快捷式,两者没有区别。
操作演示
[root@prolinux ~]# ls -l
total 0
drwxr-xr-x. 2 root root 36 Mar  3 19:21 files
drwxr-xr-x. 2 root root 36 Feb 26 15:10 ProLinux

[root@prolinux ~]# ll
total 0
drwxr-xr-x. 2 root root 36 Mar  3 19:21 files
drwxr-xr-x. 2 root root 36 Feb 26 15:10 ProLinux
查看隐藏文件

和之前一样,加 -a 参数配合使用。

操作演示
[root@prolinux ~]# ls -al
总用量 52
dr-xr-x---.  4 root root 4096 8月  27 2019 .
dr-xr-xr-x. 17 root root 4096 8月  27 2019 ..
-rw-------.  1 root root  948 8月  27 2019 anaconda-ks.cfg
-rw-------.  1 root root 8403 8月  27 2019 .bash_history
-rw-r--r--.  1 root root   18 12月 29 2013 .bash_logout
-rw-r--r--.  1 root root  176 12月 29 2013 .bash_profile
-rw-r--r--.  1 root root  176 12月 29 2013 .bashrc
-rw-r--r--.  1 root root  100 12月 29 2013 .cshrc
drwxr-xr-x   4 root root   48 8月  27 2019 .kube
drwxr-----.  3 root root   18 8月  27 2019 .pki
-rw-r--r--.  1 root root  129 12月 29 2013 .tcshrc
-rw-------   1 root root 4243 8月  27 2019 .viminfo
只看目录,不看子目录
操作演示
[root@prolinux ~]# ls -dl files/
drwxr-xr-x. 2 root root 36 Mar  3 19:21 files/
查看内容,包括子目录
操作演示
[root@prolinux ~]# ls -R
.:
files  ProLinux

./files:
bar.txt  foo.txt

./ProLinux:
bar.txt  foo.txt

加上 -l 参数,文件信息更详细。

操作演示
[root@prolinux ~]# ls -Rl
.:
total 0
drwxr-xr-x. 2 root root 36 Mar  3 19:21 files
drwxr-xr-x. 2 root root 36 Feb 26 15:10 ProLinux

./files:
total 8
-rw-r----r----. 1 root root 19 Mar  3 19:21 bar.txt
-rw-r----r----. 1 root root 19 Mar  3 19:21 foo.txt

./ProLinux:
total 8
-rw-r----r----. 1 root root 15 Feb 26 15:12 bar.txt
-rw-r----r----. 1 root root 15 Feb 26 15:12 foo.txt

5.4. 编辑文件

在Linux服务器环境(非图形界面)下,我更多使用 vim 编辑文件。vim 强大而丰富的功能吸引了很多人,有人愿意花几天小时甚至几周学习 "如何用好vim编辑器",并且没有一点怨言。

但是,vim 非常不适合新人。

如果你只是改个数据密码之类的简单需求,花几分钟了解一下 nano 则是更好的选择。

为什么不在Windows上改完文件,通过工具上传到服务器?

大部分时候,仅仅修改一下数据密码或邮箱,直接用 vimnano 之类的命令行编辑器操作就行了。
不想在本地改完了还要操作上传,太麻烦了。

按照惯例,先安装Nano编辑器:

yum install -y nano

5.4.1. 用Nano创建和打开文件

如果你想创建新文件或打开文件,命令是这样:

nano

这样:

nano foo.txt

或者这样:

nano /data/foo.txt
直接指定文件的绝对路径时,文件的父目录必须存在,否则会报错。比如 nano /data/foo.txt 中的 /data 。如果不存在,不要忘了使用 mkdir /data 创建。

第二、三种方法也可以用来打开一个已经存在的文件。

请记住,如果你要打开一个不在当前目录的文件,需要像第三个例子一样写明文件的绝对路径或相对路径。

以下是用Nano编辑器打开文件的截图:

ch05.s3-1

如你所见,在编辑器窗口底部有键盘快捷键的提示信息。方便执行一些基本操作,比如复制粘贴文字。退出编辑器和查看帮助的快捷键也都在这里。

5.4.2. 编辑内容

在Nano编辑器中,敲击键盘就能输入内容,Enter 键可以换行。

怎么移动光标呢?

试一试键盘右下方的上下左右箭头按键。

我从其它地方复制了文字,怎么粘贴进Nano编辑框?

鼠标右键,找到粘贴功能(常见 "粘贴""paste"),选中单击。

5.4.3. 在Nano编辑器中保存文件

保存文件的快捷键是 Ctrl+o (不要按错了哦!是字母o)。当你按了快捷键,编辑器会询问保存文件名称(或确认文件名称)。文件名称设置完毕,按 Enter 键保存文件。

保存文件操作截图:

ch05.s3-2

保存完毕后,按 Ctrl+x 可以退出。

在没保存的情况下,直接按 Ctrl+x,然后输入文件名称,一步完成保存退出操作。是不是更快呢?

5.4.4. 总结

关于Nano编辑器的基本使用就讲到这里。如果有更加复杂的操作,在Windows上改完再上传是更快的办法。

用Nano本就是图简单,花半个小时学这个就不值得了。

5.5. 打印内容

5.5.1. cat 命令

有时,想把文件所有内容打印到屏幕上:

cat foo.txt
这是测试文本。
这是测试文本1。
这是测试文本2。

也可以打印行号:

cat -n foo.txt
     1	这是测试文本。
     2	这是测试文本1。
     3	这是测试文本2。

5.5.2. less 命令

相较于 cat 命令将文件所有内容打印到屏幕上,less 命令仅仅打印一屏的行为非常奇特。

为什么 less 会这样呢?

在文件内容特别多时,文件内容分批次打印到屏幕才是方便的。不然,所有内容全部打印到屏幕,屏幕至少滚动10秒钟才会停下,我自然也找不到我想要的内容。

5.6. 压缩(打包)和解压文件

5.6.1. 准备测试文件

cd
mkdir -p prolinux
echo "测试文本1" > prolinux/foo.txt
echo "测试文本2" > prolinux/bar.txt
echo "测试文本3" > quz.txt

5.6.2. 压缩(打包)和解压演示

压缩(打包)演示

下文出现的 foo.tar.gz 是相对路径 ./foo.tar.gz 的简化版。根据实际情况,你可以指定任何相对或绝对路径,比如:

  • ../foo.tar.gz

  • ~/foo.tar.gz

  • /tmp/foo.tar.gz

cd
tar zcvf foo.tar.gz prolinux/ quz.txt
解释
zcf

创建一个压缩包文件

v

显示详细过程

foo.tar.gz

压缩包文件名

files/

指定加入压缩包的目录,紧跟在压缩包文件名之后

quz.txt

指定加入压缩包的文件,紧跟在压缩包文件名之后

压缩包文件名后可以指定多个目录或文件哦!自己动手试试看。
查看压缩包内容
tar tf foo.tar.gz
解压演示

解压内容到目录 foo 中:

mkdir -p foo
cd foo
tar xvf ../foo.tar.gz
解释
xf

解压文件

v

显示详细过程

foo.tar.gz

等待解压的(压缩包)文件名

说明

尽量将需要打包的目录或文件放到同一个目录下,这样本节演示的压缩和解压方法就是万能的。不再需要学更复杂的操作。作为Linux老司机,我极少遇到解决不了的。

如果解决不了怎么办?

那我就分别打几个压缩包,这样更快。

5.7. 压缩不同目录下的文件

在你没遇到这个情况的时候,请你跳过本节内容。在需要时,再来看看。

5.7.1. 准备测试文件

  1. 在绝对路径 /tmp (目录)下创建5个1M的文件,文件内容为随机数据:

mkdir -p /tmp/files
dd if=/dev/urandom bs=1M count=5 of=/tmp/files/tmp_random_file
split -d -b 1M /tmp/files/tmp_random_file /tmp/files/tmp_random_file.
rm -f /tmp/files/tmp_random_file

/tmp/files 目录下,会自动生成如下文件:

tmp_random_file.00  tmp_random_file.01  tmp_random_file.02  tmp_random_file.03  tmp_random_file.04
  1. 在相对路径 prolinux/ (目录)下创建5个1M的文件,文件内容为随机数据:

cd ~
mkdir -p prolinux/
dd if=/dev/urandom bs=1M count=5 of=prolinux/prolinux_random_file
split -d -b 1M prolinux/prolinux_random_file prolinux/prolinux_random_file.
rm -f prolinux/prolinux_random_file

~/prolinux 目录下,会自动生成如下文件:

prolinux_random_file.00  prolinux_random_file.01  prolinux_random_file.02  prolinux_random_file.03  prolinux_random_file.04

5.7.2. 带路径打包

tar zcvf foo.tar.gz /tmp/files

"foo.tar.gz" 内容列表如下:

tmp/files/
tmp/files/tmp_random_file.03
tmp/files/tmp_random_file.01
tmp/files/tmp_random_file.00
tmp/files/tmp_random_file.04
tmp/files/tmp_random_file.02

5.7.3. 不带路径打包

方法一:

cd /tmp/files/
tar zcvf ~/foo.tar.gz tmp_random_file.*

方法二:

tar zcvf ~/foo.tar.gz -C /tmp/files/ tmp_random_file.*

"foo.tar.gz" 内容列表如下:

tmp_random_file.00
tmp_random_file.01
tmp_random_file.02
tmp_random_file.03
tmp_random_file.04

第一种方法逻辑更简单,第二种方法一行搞定。我推荐你在多数情况下使用第一种方法。

5.7.4. 多目录打包

将以下文件打包到压缩文件 foo.tar.gz

  • /tmp 下的 files 目录及其文件

  • ~/prolinux 目录下以 prolinux_random_file. 开头的文件

tar zcvf ~/foo.tar.gz -C /tmp/ files/ -C ~/prolinux/ prolinux_random_file.{00..04}

tar zcvf ~/foo.tar.gz -C /tmp/ files/ -C ~/prolinux/ .
使用 -C 参数时,不能使用 prolinux_random_file.* 这样的星号通配符。

"foo.tar.gz" 内容列表如下:

files/tmp_random_file.00
files/tmp_random_file.01
files/tmp_random_file.02
files/tmp_random_file.03
files/tmp_random_file.04
prolinux_random_file.00
prolinux_random_file.01
prolinux_random_file.02
prolinux_random_file.03
prolinux_random_file.04

5.7.5. 归档文件和压缩文件的区别

  • 归档文件只是把多个文件打包放一起,包文件大小更大。

  • 压缩文件使用了压缩算法,包文件更小。

创建归档文件:"bar.tar",创建压缩文件:"foo.tar.gz"

tar vcf ~/bar.tar ~/prolinux
tar zvcf ~/foo.tar.gz ~/prolinux

查看两个文件大小,单位 kb

du -sk ~/foo.tar.gz ~/bar.tar

可以明显看出 "foo.tar.gz"(5124kb) 比 "bar.tar"(5132kb) 更小:

5124	/root/foo.tar.gz
5132	/root/bar.tar

再看看两个文件类型信息:

file ~/foo.tar.gz ~/bar.tar

"foo.tar.gz"zip 压缩的,"bar.tar" 仅仅是将文件打包。

/root/foo.tar.gz: gzip compressed data, from Unix, last modified: Mon Apr  6 14:48:30 2020
/root/bar.tar:    POSIX tar archive (GNU)

5.7.6. 清理测试文件

rm -f ~/foo.tar.gz ~/bar.tar
rm -rf prolinux /tmp/files

5.8. 统计大小

du 命令基本用法: du -sh 目录或文件路径1 [目录或文件路径2] …​,比如:

du -sh foo.tar.gz

5.8.1. 查看文件大小

du -sh ~/foo.tar.gz
屏幕内容
58M     /root/foo.tar.gz

5.8.2. 统计目录大小

du -sh /usr
屏幕内容
1.7G    /usr

5.8.3. 统计多个目录大小

du -sh /usr/* /var /tmp
屏幕内容
67M    /usr/bin
48K    /usr/etc
4.0K   /usr/games
13M    /usr/include
913M   /usr/lib
138M   /usr/lib64
40M    /usr/libexec
169M   /usr/local
40M    /usr/sbin
291M   /usr/share
75M    /usr/src
0      /usr/tmp
277M   /var
21M    /tmp

5.8.4. 其它选择

du 命令不是唯一的选择。你也可以这样查看文件大小:

ls -hl
屏幕内容
total 5.1M
-rw-r--r-- 1 root root 5.1M Apr  6 17:06 foo.tar.gz
drwxr-xr-x 2 root root 4.0K Apr  6 17:06 prolinux

但是,ls -hl 不会统计目录下所有文件的总大小,仅仅显示目录大小为 "4.0K"。最终,还是 du 命令更香。

5.9. 查看文件类型

在第三章我讲过,文件名或扩展名不决定文件类型。那怎么判断文件类型呢?

file 命令可以检测文件类型。它还会显示文本文件的字符编码,简直是诊断乱码问题的神器。

5.9.1. 准备测试文件

cd
mkdir -p prolinux
touch prolinux/foo.txt
echo 'This is a test text.' > prolinux/bar.txt
echo '这是测试文本。' > prolinux/quz.txt
tar zcf foo.tar.gz prolinux

5.9.2. 运行 file 命令

file 命令基本用法: file 文件路径,比如:

file prolinux/foo.txt

检测多个文件的类型:

file prolinux/*.txt foo.tar.gz
屏幕内容
prolinux/bar.txt: ASCII text
prolinux/foo.txt: empty
prolinux/quz.txt: UTF-8 Unicode text
foo.tar.gz:       gzip compressed data, from Unix, last modified: Mon Apr  6 17:06:11 2020

如果你学过HTML,那你一定对这个眼熟:

file -i prolinux/*.txt foo.tar.gz
屏幕内容
prolinux/bar.txt: text/plain; charset=us-ascii
prolinux/foo.txt: inode/x-empty; charset=binary
prolinux/quz.txt: text/plain; charset=utf-8
foo.tar.gz:       application/x-gzip; charset=binary

加上 -i 参数,会打印出文件的MIME类型。

5.10. 清空内容

一点准备工作
cd
mkdir -p prolinux
echo 'foo123' > prolinux/foo.txt
echo 'bar123' > prolinux/bar.txt
ll prolinux

清空文件内容:

echo > prolinux/foo.txt

echo -n '' > prolinux/bar.txt

不加 -n 参数时,"foo.txt" 中有一个换行符(\n)。看看文件大小:

ls -l prolinux/*.txt
屏幕内容
-rw-r--r-- 1 root root  0 Apr  6 17:32 prolinux/bar.txt
-rw-r--r-- 1 root root  1 Apr  6 17:32 prolinux/foo.txt

"foo.txt" 大小为1个字节,"bar.txt" 大小为0个字节。

5.10.1. 扩展内容

如果你对换行符有兴趣,可以这样看:

cat -A prolinux/foo.txt
屏幕内容
$

上面的美元符号表示换行符(\n)。

也可以通过查看十六进制确认:

hexdump prolinux/foo.txt
屏幕内容
0000000 000a
0000001

上面的 "0a" 是换行符(\n)的十六进制表示。

5.11. 删除文件

不要在Linux系统上删除任何系统目录(比如 rm -rf /rm -rf /usr 等等)。否则数据丢失,系统崩溃无法启动。

rm 命令基本用法:rm 目录或文件路径,比如:

rm prolinux/foo.txt

rm 在删除前会提示 "remove regular file ‘prolinux/foo.txt’? ",询问是否删除。

输入 y,按 Enter 键即可删除。

不想删除了?两种方法:

  1. 输入 n,按 Enter

  2. Ctrl+c 键终止操作

如果不想要这个提示,加上 -f 参数:

rm -f prolinux/foo.txt

5.11.1. 删除目录

rm -r prolinux

rm 同样会询问是否删除。输入 y,按 Enter 键即可删除目录。

不想要提示怎么办?和之前一样,加上 -f 参数:

rm -rf prolinux

5.11.2. 误删文件怎么办?

Linux不像Windows桌面一样有 "回收站",使用 rm 删除的文件没有后悔药,无法找回。在这之前,一个良好的习惯尤为重要:

新建名为 trash 的目录,作为自己的文件回收站。将等待删除的文件移动(mv 命令)到这个目录,每隔一段时间删除 trash 目录下的所有文件。

操作演示
mkdir -p ~/trash
mv prolinux ~/trash

# 每隔一段时间清理回收站
rm -rf ~/trash/*

其实,我在修改重要文件时,也有类似的习惯。我会先复制一份保存做备份,防止误操作。假如改错东西,可以用备份恢复到最初状态。

操作演示
# 先复制一份做备份
cp prolinux/foo.txt prolinux/foo.txt.bak

# 然后,再修改
nano prolinux/foo.txt

# 如果后悔了,这样恢复
cp prolinux/foo.txt.bak prolinux/foo.txt

5.12. 复制文件

cp 命令:复制目录或文件。

5.12.1. 基础用法

cp 被复制的文件 新的文件名或路径
常用参数
-r

复制目录

-v

显示详细过程

--help

查看帮助信息

5.12.2. 操作演示

开始之前

为练习提前创建目录和文件:

cd
mkdir -p ~/prolinux
touch ~/prolinux/foo.txt ~/prolinux/bar.txt
复制文件

复制文件,保持文件名不变:

cp -v ./prolinux/foo.txt /tmp/

复制并修改文件名:

cp -v ./prolinux/foo.txt /tmp/new_foo.txt
如果指定的新文件名或路径已经存在,cp 命令会提示 "cp: overwrite ‘/tmp/foo.txt’?"",询问是否覆盖已经有的文件。输入 y,按 Enter 键就行。

在同一个目录下复制一个新文件:

cp -v ./prolinux/bar.txt ./prolinux/new_bar.txt

cd ~/prolinux/
cp -v bar.txt new_bar.txt
复制目录

复制当前目录下的 prolinux 文件夹到 /tmp 目录下:

cp -vr prolinux/ /tmp/

查看复制前后的区别:

find ~/prolinux/ /tmp/prolinux/
屏幕内容
/root/prolinux/
/root/prolinux/bar.txt
/root/prolinux/foo.txt
/tmp/prolinux/
/tmp/prolinux/bar.txt
/tmp/prolinux/foo.txt

如果复制文件一样,可以指定新的目录 "prolinux_test"

`cp -vr prolinux/ /tmp/prolinux_test`

复制后,"foo.txt" 的路径会是这样:"/tmp/prolinux_test/foo.txt"

试一试下面这样复制目录:

cp -vr prolinux/ /tmp/prolinux_test
cp -vr prolinux/ /tmp/prolinux_test

find prolinux/ /tmp/prolinux_test

恭喜你?
你陷入了套娃模式~

结束之后

删除为练习创建的目录和文件:

cd
rm -rf prolinux /tmp/prolinux*

5.13. 移动(重命名)文件

mv 命令:移动(重命名)文件。

5.13.1. 基础用法

mvcp 的基础用法类似。

mv 被移动的文件 新文件名或路径
常用参数
-v

显示详细过程

--help

查看帮助信息

5.13.2. 操作演示

开始之前

为练习提前创建目录和文件:

cd
mkdir -p ~/prolinux
touch ~/prolinux/foo.txt ~/prolinux/bar.txt
移动文件

移动文件,保持文件名不变:

mv -v ./prolinux/foo.txt /tmp/

移动并修改文件名:

mv -v ./prolinux/foo.txt /tmp/new_foo.txt

修改文件名,不改变文件位置:

mv -v ./prolinux/bar.txt ./prolinux/new_bar.txt

cd ~/prolinux/
mv -v bar.txt new_bar.txt
移动目录

移动当前目录下的 prolinux 文件夹到 /tmp 目录下:

mv -v prolinux/ /tmp/

查看移动后的情况:

find /tmp/prolinux/
屏幕内容
/tmp/prolinux/
/tmp/prolinux/bar.txt
/tmp/prolinux/foo.txt

如果移动文件一样,可以指定新的目录 "prolinux_test"

`mv -v prolinux/ /tmp/prolinux_test`

移动后,"foo.txt" 的路径会是这样:"/tmp/prolinux_test/foo.txt"

结束之后

删除为练习创建的目录和文件:

cd
rm -rf prolinux /tmp/prolinux*

6. 文件属性

6.1. 简介

6.1.1. 看看我是谁

id 命令可以打印用户和组信息:

id
屏幕内容
uid=0(root) gid=0(root) groups=0(root)

       当前用户名:root,uid为0

用户所属组:root,gid为0

在当前用户和组的情况下,创建目录和文件后文件属性会显示 "root root" 字样,表示由root用户创建。

当然,id 也可以打印指定用户的信息: id 用户名。比如,id nobody

6.1.2. 一点点准备

创建测试用目录和文件:

mkdir -p ~/prolinux
echo "foo123" > ~/prolinux/foo.txt
echo "bar1234567" > ~/prolinux/bar.txt
chown nobody ~/prolinux/bar.txt

6.1.3. 什么是用户、组和文件权限

查看目录和文件属性:

ls -dl ~/prolinux ~/prolinux/*.txt
屏幕内容
drwxr-xr-x 2 root   root 4096 Jun 15 14:18 /root/prolinux
-rw-r--r-- 1 nobody root   11 Jun 15 14:19 /root/prolinux/bar.txt
-rw-r--r-- 1 root   root    7 Jun 15 14:19 /root/prolinux/foo.txt

"root root""nobody root" 表示用户、组设置状态。

"drwxr-xr-x""-rw-r—​r--" 表示文件权限(读、写、执行权限)设置状态。

6.1.4. 文件属性中的用户、组和文件权限是什么关系

用户、组设置

类似游乐园的门票,属于某种形式的许可或凭证。通过门票类型确定游客类型属于A类还是B类,没有门票(许可)就不能进园区(访问文件)。这个层面,只关心游客类型,不关心游客进去后玩哪种娱乐项目。

用户和组设置作为文件安全的第一道大门,起到甄别用户或程序是否有访问权限的作用。
文件权限设置

类似进入游乐园后,A类游客只能玩A类包含的娱乐项目(旋转木马、摩天轮),B类游客也只能玩B类包含的娱乐项目(云霄飞车、激流勇进、海盗船)。
A类游客不允许玩儿B类的项目,要玩儿云霄飞车(读或写文件)就得补票,补B类型的门票(重新设置文件权限)。

文件权限设置可以让系统知道:用户或程序对文件有读权限、写权限还是执行权限。没有权限,系统会拒绝操作请求。

6.2. 文件用户和组

6.2.1. 每个文件都属于一个用户和一个组

Linux中的每个文件必定属于一个用户和一个组。不管用户还是组都只能一个,不能多个。

查看刚才准备的目录和文件,打印更简洁的文件属性:

ls -dl ~/prolinux/ ~/prolinux/*.txt | awk '{print "用户:"$3"    组:"$4"    名称:"$NF}'
屏幕内容
用户:  root    组:root    名称:/root/prolinux/
用户:nobody    组:root    名称:/root/prolinux/bar.txt
用户:  root    组:root    名称:/root/prolinux/foo.txt

用户和组不一定要相同,比如

用户:nobody    组:root    名称:/root/prolinux/bar.txt

上面这行表示文件 "/root/prolinux/bar.txt" 属于用户 "nobody" 和 组 "root"

再看看 "nobody" 用户的信息:

id nobody
屏幕内容
uid=99(nobody) gid=99(nobody) groups=99(nobody)

可以看到用户 "nobody" 和 组 "root" 没有关系。

6.2.2. 修改文件的用户和组设置

chown -v 中的 "-v" 参数仅为打印日志信息,无实际作用,可以忽略。

"~/prolinux/foo.txt" 用户和组都修改为 "nobody"

chown -v nobody:nobody ~/prolinux/foo.txt
屏幕内容
changed ownership of ‘/root/prolinux/foo.txt’ from root:root to nobody:nobody

确认设置状态:

ls -l ~/prolinux/foo.txt
屏幕内容
-rw-r--r-- 1 nobody nobody 7 Jun 15 14:19 /root/prolinux/foo.txt

看到 "nobody nobody" 说明设置成功。

6.2.3. 修改目录的用户和组设置

chown -v 中的 "-v" 参数仅为打印日志信息,无实际作用,可以忽略。

-R 参数表示修改目录以及目录下的所有文件用户和组设置。

修改 "~/prolinux/" 目录的用户和组为 "root"

chown -vR root:root ~/prolinux/
屏幕内容
ownership of ‘/root/prolinux/bar.txt’ retained as root:root
changed ownership of ‘/root/prolinux/foo.txt’ from nobody:nobody to root:root
ownership of ‘/root/prolinux/’ retained as root:root

查看目录和目录下的文件属性:

ls -dl ~/prolinux/ ~/prolinux/*.txt
屏幕内容
drwxr-xr-x 2 root root 4096 Jun 15 14:18 /root/prolinux/
-rw-r--r-- 1 root root   11 Jun 15 14:19 /root/prolinux/bar.txt
-rw-r--r-- 1 root root    7 Jun 15 14:19 /root/prolinux/foo.txt

三行都是 "root root",设置成功。

6.2.4. 同时设置多个目录或文件的用户和组

直接在 chown 后加上路径即可,比如

chown -R root:root ~/prolinux/foo.txt ~/prolinux/

chown root:root ~/prolinux/foo.txt ~/prolinux/bar.txt

6.3. 文件权限

6.3.1. 理解文件权限标志

权限分组

每个文件或目录都有三个基于用户的权限组:

所有者

文件的所有者,具体指某个用户

文件所属的组

其它用户

所有者和组以外的用户

权限类型

每个文件或目录拥有三个基础权限类型:

可读

读取文件内容的权限

可写

写或修改文件的权限

可执行

查看目录列表(如 ls -l foo/)或执行脚本(如 sh ./foo.sh)的权限

chmod

Linux系统用 chmod 命令修改文件权限,chmod 有多种表示法(字母法和数字法)指定文件权限。如 chmod +x filenamechmod 755 filename。本文仅描述基于八进制的数字法。

数字法有四个八进制数字组成。如 "0755",不过会简写成 "755"

第一个 "0" 涉及不常用功能,直接忽略之,熟悉后面三个数字即可。

Table 2. 数字法的基础数字
权限符号 八进制数字 描述

r

4

可读

w

2

可写

x

1

可执行

Table 3. 数字法对照表
权限符号组 八进制数字 描述

rwx

7

可读可写可执行

rw-

6

可读可写可执行

r-x

5

可读可写可执行

r--

4

可读可写可执行

-wx

3

可读可写可执行

-w-

2

可读可写可执行

--x

1

可读可写可执行

0

可读可写可执行

看不明白?没关系,看后面…​…​

一点点准备

为详细说明文件权限,提前设置文件的用户和组:

chown -R root:root ~/prolinux/
chown root:nobody ~/prolinux/foo.txt
文件权限说明

不管是系统管理,还是编程写代码,数字法用得最多。字母法和数字法之间的转换属于日常,下文用表格来解释。

提前解释下 stat 的参数
"%A"

第1列,文件权限字母表示法,如 "drwxr-xr-x"

"%a"

第2列,文件权限数字表示法,如 "755"

"%U"

第3列,文件所属用户,如 root"

"%G"

第4列,文件所属组,如 "root"

"%n"

第5列,目录或文件名称,如 "/root/prolinux/"


示例1


列出 ~/prolinux/ 目录的文件属性:

ls -dl ~/prolinux/
stat -c '%A %a %U %G %n' ~/prolinux/
屏幕内容
drwxr-xr-x 2 root root   4096 Jun 15 14:18 /root/prolinux/
drwxr-xr-x 755 root root /root/prolinux/

用户和组

root

root

其它用户

权限分组

所有者权限

组权限

其它用户权限

文件权限

目录

可读

可写

可执行

可读

可执行

可读

可执行

权限模式
字母表示法

d

r

w

x

r

-

x

r

-

x

权限标识

4

2

1

4

1

4

1

权限模式
数字表示法

7

5

5


示例2


列出 ~/prolinux/bar.txt 的文件属性:

ls -l ~/prolinux/bar.txt
stat -c '%A %a %U %G %n' ~/prolinux/bar.txt
屏幕内容
-rw-r--r-- 1 root root     11 Jun 16 10:41 /root/prolinux/bar.txt
-rw-r--r-- 644 root root /root/prolinux/bar.txt

用户和组

root

root

其它用户

权限分组

所有者权限

组权限

其它用户权限

文件权限

文件

可读

可写

可读

可读

权限模式
字母表示法

-

r

w

-

r

-

-

r

-

-

权限标识

4

2

4

4

权限模式
数字表示法

6

4

4


示例3


列出 ~/prolinux/foo.txt 的文件属性:

ls -l ~/prolinux/foo.txt
stat -c '%A %a %U %G %n' ~/prolinux/foo.txt
屏幕内容
-rw-r--r-- 1 root nobody    7 Jun 16 10:41 /root/prolinux/foo.txt
-rw-r--r-- 644 root nobody /root/prolinux/foo.txt

用户和组

root

nobody

其它用户

权限分组

所有者权限

组权限

其它用户权限

文件权限

可读

可写

可读

可读

权限模式
字母表示法

-

r

w

-

r

-

-

r

-

-

权限标识

文件

4

2

4

4

权限模式
数字表示法

6

4

4

6.3.2. 修改文件权限

chmod -v 中的 "-v" 参数仅为打印日志信息,无实际作用,可以忽略。
chmod -v 755 ~/prolinux/foo.txt
屏幕内容
mode of ‘/root/prolinux/foo.txt’ changed from 0644 (rw-r--r--) to 0755 (rwxr-xr-x)

6.3.3. 修改目录权限

chmod -v 中的 "-v" 参数仅为打印日志信息,无实际作用,可以忽略。

-R 参数表示修改目录以及目录下的所有文件权限设置。

chmod -vR 755 ~/prolinux/
屏幕内容
mode of ‘/root/prolinux/’ retained as 0755 (rwxr-xr-x)
mode of ‘/root/prolinux/bar.txt’ changed from 0644 (rw-r--r--) to 0755 (rwxr-xr-x)
mode of ‘/root/prolinux/foo.txt’ retained as 0755 (rwxr-xr-x)

6.3.4. 同时设置多个目录和文件的权限

chmod -R 755 ~/prolinux/foo.txt ~/prolinux/

chmod 644 ~/prolinux/foo.txt ~/prolinux/bar.txt

7. 输入输出重定向

输入输出重定向,常偷懒称作IO重定向。

IO是Input/Output的简写。

7.1. 什么是IO重定向

“用 键盘 打字,屏幕 能实时看到输入的文字。”

  • 键盘是一种输入(input)设备,Linux中称作 标准输入(stdin)设备

  • 屏幕是一种输出(output)设备,Linux中称作 标准输出(stdout)设备

“打错字时,屏幕上能看到醒目的软件错误提示。比如, 发现未知单词 Lxinu。”

  • 屏幕是一种错误输出(output)设备,Linux中称作 标准错误输出,或 错误输出(stderr)设备

IO重定向是Linux系统中常用的功能,可以在执行命令时改变标准输入/输出设备。

打印内容到屏幕的例子:

echo prolinux

加入重定向后的例子:

echo prolinux > ~/foo.txt

上面的例子,将本该显示到屏幕的执行结果保存到文件 "foo.txt"。通过重定向功能将输出设备从屏幕改成了文件。

7.2. 标准输出重定向(stdout)

">""1>" 符号

覆盖写入,文件内容先被清空,然后写入新内容。

">>""1>>" 符号

追加写入,新内容追加到文件末尾,不影响已有内容。

7.2.1. 什么是标准输出重定向

标准输出重定向把命令的执行结果(内容)写入文件,而不是显示在屏幕上。

除了文件,标准输出重定向还可以 “写入” 其它地方。这些不在本文讨论范围。

7.2.2. 标准输出重定向能做什么

覆盖写入

在终端执行某些命令时,通常会在屏幕上看到执行结果。比如:

[root@prolinux ~]# ls /usr/lib
binfmt.d  grub    modprobe.d      rpm               systemd
debug     kbd     modules         sendmail          tmpfiles.d
dracut    kdump   modules-load.d  sendmail.postfix  tuned
firmware  kernel  polkit-1        sse2              udev
games     locale  python2.7       sysctl.d          yum-plugins

ls /usr/lib 的执行结果较少,显示没问题。

在系统日志中查找服务启动日志,这样的情况就有问题了。

试一试:

journalctl | grep Starting
执行结果
8月 16 16:10:14 localhost.localdomain kernel: SELinux:  Starting in permissive mode
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting Swap.
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting -.slice.
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting udev Control Socket.
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting System Slice.
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting Slices.
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting udev Kernel Socket.
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting Local File Systems.
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting Timers.
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting Journal Socket.
8月 16 16:10:14 localhost.localdomain systemd[1]: Starting Create list of required static device nodes for the current kernel...
816 16:10:14 localhost.localdomain systemd[1]: Starting Sockets.
816 16:10:14 localhost.localdomain systemd[1]: Starting dracut cmdline hook...
816 16:10:14 localhost.localdomain systemd[1]: Starting Setup Virtual Console...
816 16:10:14 localhost.localdomain systemd[1]: Starting Apply Kernel Variables...
816 16:10:14 localhost.localdomain systemd[1]: Starting Journal Service...
816 16:10:14 localhost.localdomain systemd[1]: Starting Create Static Device Nodes in /dev...
...
...
...

内容太多,屏幕可能显示不完。

再试一试:

journalctl | grep Starting > ~/out.log
"> ~/out.log" 可以用 "1> ~/out.log" 代替。

“乱码”去哪儿了?

之前在屏幕上显示的内容,写到了 "~/out.log" 文件。如下:

[root@prolinux ~]# cat ~/out.log
816 16:10:14 localhost.localdomain kernel: SELinux:  Starting in permissive mode
816 16:10:14 localhost.localdomain systemd[1]: Starting Swap.
816 16:10:14 localhost.localdomain systemd[1]: Starting -.slice.
816 16:10:14 localhost.localdomain systemd[1]: Starting udev Control Socket.
816 16:10:14 localhost.localdomain systemd[1]: Starting System Slice.
816 16:10:14 localhost.localdomain systemd[1]: Starting Slices.
...
...
...
追加写入

一个简单的例子:

echo line1 > ~/foo.txt
echo line2 >> ~/foo.txt
echo line3 >> ~/foo.txt

看看文件内容:

[root@prolinux ~]# cat ~/foo.txt
line1
line2
line3

可以看到,新内容始终在结尾处追加写入。

看看覆盖写入会发生什么:

echo line4 > ~/foo.txt

当前的文件内容:

[root@prolinux ~]# cat ~/foo.txt
line4

7.3. 标准输入重定向(stdin)

"<""0<" 符号

将文件内容作为命令输入。

"<<" 符号(Here Document)

一种特殊目的的输入重定向,在交互式程序或命令中实现 "块" 输入。

7.3.1. 什么是标准输入重定向

执行命令时,用标准输入重定向能从文件内容或其它命令结果读取参数。

标准输入重定向常用于需要大量输入或某些交互式场景。

这样,我们不用手动输入参数,也可以运行命令。

7.3.2. 标准输入重定向能做什么

示例1:wc命令

下面两个示例分别演示如何用 wc 命令统计 "foo.txt" 的行数。

准备测试文件:

echo line1 > ~/foo.txt
echo line2 >> ~/foo.txt
echo line3 >> ~/foo.txt

统计行数:

命令1
wc -l ~/foo.txt
命令1-执行结果
3 /root/foo.txt

使用标准输入重定向统计行数:

命令2
wc -l < ~/foo.txt
命令2-执行结果
3

两个命令得到相同的文件行数:3。

命令1指定了参数:"~/foo.txt",所以结果中包含文件名。

命令2则没有指定文件名,而是通过标准输入重定向读取文件内容后,将文件内容传递给 wc 命令。

一个命令指定文件名,一个命令直接传递文件内容。

示例2:wc命令(Here Document)

Here Document 可以实现在没有 "foo.txt" 文件的情况下,统计出行数。

命令3
wc -l << EOF
line1
line2
line3
EOF
命令3-输出
3

命令3同样得到文件行数:3。

命令3中有两个重点:

  1. "<<",Here Document符号,表示标准输入重定向;

  2. "EOF",内容起止符号(成对出现),表示内容块开始和终止。

终止EOF符号前不能有空格。

7.3.3. 延伸

命令1/2/3执行结果相同,但实用程度排名则是这样:

正常 << 便捷 << 超级实用

对标准输入重定向理解到位,可是能极大提升Linux使用效率。

场景:导入/导出MySQL数据

Linux作为开发环境、服务器系统首选,搭配MySQL使用是很自然的事情。导入/导出MySQL数据基本成为了日常操作。

事实上,99%的人都是在用GUI图形工具处理导入导出。实际上,更简单的操作应该是这样:

使用标准输出重定向导出
mysqldump -u用户名 -p密码 数据库名称 > backup_数据库名称_2021xxxx.sql
使用标准输入重定向导入
mysql -u用户名 -p密码 数据库名称 < backup_数据库名称_2021xxxx.sql
场景:非交互式创建文件
cat << EOF > ~/foo.txt
line1
line2
line3
EOF

在脚本、技术文档或文章中用 "<< EOF" 这样的组合实在是非常舒服的一件事情。

7.4. 错误输出重定向(stderr)

错误输出重定向和标准输出重定向都是把命令的执行结果(内容)写入文件,而不是显示在屏幕上。
不同的地方在于,错误输出重定向仅在命令执行失败时有效。具体的,可以看后面的例子。

除了文件,错误输出重定向还可以 “写入” 其它地方。这些不在本文讨论范围。

在命令行中单个 "2>" 和两个 "2>>" 的用法和标准输出重定向相同。

注意是数字 2 不是 1
极少数情况下会用到 2>&1"2>&1" 表示将错误输出(stderr)重定向到标准输出(stdout)。

7.4.1. 例子

例子1

故意查看不存在的文件:

ls -l /usr/include ~/abcdefghijk /test/foo.txt
屏幕内容
[root@prolinux ~]# ls -l /usr/include ~/abcdefghijk /test/foo.txt
ls: 无法访问/root/abcdefghijk: 没有那个文件或目录
ls: 无法访问/test/foo.txt: 没有那个文件或目录
/usr/include:
总用量 0
drwxr-xr-x. 2 root root 26 827 2019 python2.7

可以看到 "/usr/include" 的文件,另外两个文件则报错。

例子2

用错误输出重定向改造下,错误提示写到文件中:

ls -l /usr/include ~/abcdefghijk /test/foo.txt 2>~/error.log
屏幕内容
[root@prolinux ~]# ls -l /usr/include ~/abcdefghijk /test/foo.txt 2>~/error.log
/usr/include:
总用量 0
drwxr-xr-x. 2 root root 26 827 2019 python2.7

这次屏幕看起来干净些,错误提示也“消失了”。

看看 "~/error.log" 的内容:

[root@prolinux ~]# cat ~/error.log
ls: 无法访问/root/abcdefghijk: 没有那个文件或目录
ls: 无法访问/test/foo.txt: 没有那个文件或目录

8. 管道

8.1. 管道

管道("|")可以将两个命令连接起来,上个命令的标准输出(stdout)作为下个命令的标准输入(stdin)。
结合管道可以完成更加复杂的命令操作。

8.1.1. 基础用法

命令1 | 命令2 | 命令3 | ... | 命令N
管道前后的空格只是为了好看。

8.1.2. 示例

列出 "/usr" 目录下的前5个文件或目录
ls -l /usr | head -n 5
输出
total 124
dr-xr-xr-x.   2 root root 36864 Feb  4 14:08 bin
drwxr-xr-x.   2 root root  4096 Apr 11  2018 etc
drwxr-xr-x.   2 root root  4096 Apr 11  2018 games
drwxr-xr-x.  46 root root  4096 Jul 11  2020 include
打印运行进程的用户名
ps aux | tail -n +2 | cut -d ' ' -f 1 | sort -u
输出
chrony
dbus
mysql
nginx
nobody
polkitd
root
tcpdump
参数说明
排除标题行

tail -n +2 可以过滤 ps aux 输出的第一行(标题行),最后只打印第二行到最后一行

分列

cut -d ' ' -f 1 表示用空格分隔行,打印第一列

排序去重

sort -u

这个示例比前面的更加复杂,也充分展示了管道的强大之处。

完成这样的小case不用脚本,不用编程,简直十分跟手。

另外,不需要担心这些没见过的“陌生人”,下一章会详细介绍这些命令的使用方法和参数。

8.1.3. 延伸

极少数命令会打印内容到错误输出(stderr),管道会失效。

“怎么办呢?”

“没关系,输出重定向就行了~”

就像这样:

strace -f -p 1038 2>&1 | grep NULL
输出
[pid  7888] futex(0x1ebe544, FUTEX_WAIT_PRIVATE, 8288, NULL <unfinished ...>
[pid   889] futex(0x1ebe544, FUTEX_WAIT_PRIVATE, 8288, NULL <unfinished ...>
[pid   888] futex(0x1ebe544, FUTEX_WAIT_PRIVATE, 8288, NULL <unfinished ...>
[pid 25199] futex(0x1ebe544, FUTEX_WAIT_PRIVATE, 8288, NULL <unfinished ...>
[pid 25198] futex(0x1ebe544, FUTEX_WAIT_PRIVATE, 8288, NULL <unfinished ...>
[pid  1671] futex(0x1ebe544, FUTEX_WAIT_PRIVATE, 8288, NULL <unfinished ...>
[pid  1344] futex(0x1e8b044, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
[pid  1343] rt_sigtimedwait([HUP QUIT TERM], NULL, NULL, 8 <unfinished ...>
[pid  1314] futex(0x33bb424, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
[pid  1311] futex(0x33bb304, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
[pid  1308] futex(0x33bb154, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
[pid  1307] futex(0x33bb0c4, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
[pid  1306] futex(0x33bb034, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
[pid  1305] futex(0x33bafa4, FUTEX_WAIT_PRIVATE, 3, NULL <unfinished ...>

"2>&1" 表示将错误输出(stderr)重定向到标准输出(stdout)。

系统默认未安装 strace 命令,需要提前安装:yum install -y strace

9. 常用命令

9.1. 我在哪儿(pwd)

pwd - 查看当前(工作)目录绝对路径

9.1.1. 基础用法

pwd

无常用参数。

9.1.2. 操作演示

查看当前路径
cd /usr
pwd

cd /usr/share/zoneinfo/Asia
pwd

cd
pwd
屏幕内容
/usr

/usr/share/zoneinfo/Asia

/root

9.2. 排序和去重(sort)

sort - 将管道、标准输入或文件的行排序后,打印到标准输出

9.2.1. 基础用法

sort 文件名或路径

命令 | sort
常用参数
-u

排序后,去重

--help

帮助信息

9.2.2. 操作演示

开始之前
创建演示文件
cat << EOF > ~/foo.txt
8888
5555
5555
8888
6666
ZZZZ
1111
aaaa
3333
0000
2222
ZZZZ
1111
aaaa
3333
0000
2222
EOF

cat << EOF > ~/ip.txt
8.8.8.8
8.8.8.8
125.64.74.81
125.93.75.146
58.47.128.241
4.4.4.4
4.4.4.4
58.47.128.241
124.94.202.242
124.225.123.2
60.16.181.208
116.255.130.10
117.81.43.159
61.146.41.106
113.6.18.36
123.6.150.215
123.188.196.36
116.52.35.6
121.228.43.0
122.224.236.26
EOF
排序

方法一:从文件读取行:

sort ~/foo.txt

方法二:从管道读取行:

cat ~/foo.txt | sort

方法三:从标准输入读取行(非主流的方法):

sort << EOF
8888
5555
5555
8888
6666
ZZZZ
1111
aaaa
3333
0000
2222
ZZZZ
1111
aaaa
3333
0000
2222
EOF

以上方法都会得到相同的结果:

屏幕内容
0000
0000
1111
1111
2222
2222
3333
3333
5555
5555
6666
8888
8888
aaaa
aaaa
ZZZZ
ZZZZ
排序去重

"-u" 参数是关键。试一试:

sort -u ~/foo.txt
屏幕内容
0000
1111
2222
3333
5555
6666
8888
aaaa
ZZZZ

现在,执行结果中的重复行已经被过滤掉。

可以试一试看 cat ~/foo.txt | sort -u 又是什么样。

延伸:排序IPv4地址
sort -u -t . -k 1n,1n -k 2n,2n -k 3n,3n -k 4n,4n ~/ip.txt

偷懒的方法:

sort -u -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n ~/ip.txt
参数说明
-u

排序后,去重

-t

指定分隔符,用 "." 分隔IP地址为4列

-k

排序关键字,参数值格式:"开始列号[排序规则],结束列号[排序规则]"
比如,1n,1n 表示从第1列行首开始到第1列行尾结束,都以数字规则 "n" 排序

更加偷懒的方法:

sort -u -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 ~/ip.txt
参数说明
-u

同上

-t

同上

-n

以数字规则排序

-k

同上,用 "-n" 参数代替 "n" 后,"1n,1n" 简写成 "1,1"

以上方法都会得到相同的结果:

屏幕内容
4.4.4.4
8.8.8.8
58.47.128.241
60.16.181.208
61.146.41.106
113.6.18.36
116.52.35.6
116.255.130.10
117.81.43.159
121.228.43.0
122.224.236.26
123.6.150.215
123.188.196.36
124.94.202.242
124.225.123.2
125.64.74.81
125.93.75.146

“学废了没?”

“试试IPv6地址排序?”

“安排~”

结束之后

删除临时文件:

rm -f ~/foo.txt ~/ip.txt

9.3. 快捷方式(ln)

ln - 创建目录或文件的快捷方式,也可以称做软链接

ln 用法较多,本文仅讨论软链接。

9.3.1. 为什么要用软链接

  • 文件太大,不想移动文件;

  • 文件不能随便修改位置,可能导致软件运行出错;

  • 想加一个方便的入口;

  • …​…​

9.3.2. 基础用法

ln -s 源路径 目标路径
常用参数
-s

创建软链接

--help

帮助信息

9.3.3. 操作演示

开始之前

准备测试文件和目录:

mkdir -p /tmp/foo
echo 'Hello World!' > /tmp/foo/source.txt

看看文件:

ls -l /tmp/foo/source.txt

cat /tmp/foo/source.txt
屏幕内容
total 4
-rw-r--r-- 1 root root 13 Feb 19 22:27 /tmp/foo/source.txt

Hello World!
创建文件的快捷方式

创建 "source.txt" 的快捷方式:

ln -s /tmp/foo/source.txt ~/target.txt

看看 target.txt 的文件属性:

ls -l ~/target.txt
屏幕内容
lrwxrwxrwx 1 root root 14 Feb 19 22:30 /root/target.txt -> /tmp/foo/source.txt

箭头符号 "→" 是软链接最重要的标志。

那文件内容呢?再看:

cat ~/target.txt
屏幕内容
Hello World!

我家小朋友都看出来了,你呢?

"~/target.txt""/tmp/foo/source.txt" 的软链接。

最后强调下
  • 删除 "~/target.txt" 后,"/tmp/foo/source.txt" 还在

  • 删除 "/tmp/foo/source.txt" 后,"~/target.txt" 可就不能用了哦

创建目录的快捷方式

创建 "/tmp/foo" 的快捷方式:

ln -s /tmp/foo /tmp/foo.link

看看:

ls -l /tmp/foo.link
屏幕内容
lrwxrwxrwx 1 root root 8 Feb 19 22:48 /tmp/foo.link -> /tmp/foo

悄悄加个 "/" 在最后,再看看:

ls -l /tmp/foo.link/
屏幕内容
total 4
-rw-r--r-- 1 root root 13 Feb 19 22:27 source.txt

加不加,可是不一样的哦。

结束之后

删除临时文件:

rm -rf /tmp/foo

rm 也能删除软链接:

rm -f /tmp/foo.link ~/target.txt

9.4. 下载工具(curl)

curl - 一个用来传输数据的命令行工具(就是个功能丰富的下载工具)

curl 支持非常多的网络协议,本文仅介绍HTTP协议。

9.4.1. 基础用法

URL一定要用一对单引号包住,否则URL中的特殊符合会导致错误。
curl -I url

curl -v -I url

curl url -o 文件名

curl -H -X HTTP方法 url

curl -A "User-Agent" url
常用参数
-I

仅显示HTTP头信息

-v

显示更多HTTP信息,常用于诊断问题

-o

下载,另存为

-X

指定HTTP方法,HTTP协议的GET/POST/PUT/OPTIONS/DELETE/HEAD等等

-H

自定义HTTP头

-A

指定浏览器标识(User-Agent)

--help all

帮助信息

9.4.2. 操作演示

下载文件并保存

下载文件到当前路径,文件名为 "centos-logo-white.png"

curl 'https://www.centos.org/assets/img/centos-logo-white.png' -o centos-logo-white.png

指定文件路径:

curl 'https://www.centos.org/assets/img/centos-logo-white.png' -o /tmp/123.png

查看下载的文件:

file /tmp/123.png  centos-logo-white.png
屏幕内容
/tmp/123.png:          PNG image data, 331 x 93, 8-bit/color RGBA, non-interlaced
centos-logo-white.png: PNG image data, 331 x 93, 8-bit/color RGBA, non-interlaced

file 看到,从官网下载的CentOS LOGO图片分辨率为 "331 x 93"

查看HTTP头信息

绝对的装X神技,开发者必备的常用技能。

一秒诊断网站故障:

curl -I 'https://www.centos.org/assets/img/centos-logo-white.png'
屏幕内容
HTTP/1.1 200 OK
Date: Thu, 04 Mar 2021 12:45:45 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips
Strict-Transport-Security: max-age=31536000
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Last-Modified: Thu, 04 Mar 2021 12:25:14 GMT
ETag: "1d8f-5bcb50f3dd2d8"
Accept-Ranges: bytes
Content-Length: 7567
Content-Type: image/png

看到 "HTTP/1.1 200 OK" 表示网站能够访问。出现403/404/502情况,说明网站无法访问。

更多HTTP协议细节,请移步 MDN Web Docs
查看更多HTTP头信息

显示更多访问细节:

curl -vI 'https://www.centos.org/assets/img/centos-logo-white.png'

curl -v -I 'https://www.centos.org/assets/img/centos-logo-white.png'
屏幕内容
* About to connect() to www.centos.org port 443 (#0)
*   Trying 81.171.33.202...
* Connected to www.centos.org (81.171.33.202) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* 	subject: CN=centos.org
* 	start date: Jan 04 06:50:09 2021 GMT
* 	expire date: Apr 04 06:50:09 2021 GMT
* 	common name: centos.org
* 	issuer: CN=R3,O=Let's Encrypt,C=US
> HEAD / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.centos.org
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
......
......
指定浏览器标识(User-Agent)

模拟百度访问CentOS官网:

curl -vI 'https://www.centos.org/' -A 'Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)'
屏幕内容
* About to connect() to www.centos.org port 443 (#0)
*   Trying 81.171.33.202...
* Connected to www.centos.org (81.171.33.202) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* 	subject: CN=centos.org
* 	start date: Jan 04 06:50:09 2021 GMT
* 	expire date: Apr 04 06:50:09 2021 GMT
* 	common name: centos.org
* 	issuer: CN=R3,O=Let's Encrypt,C=US
> HEAD / HTTP/1.1
> User-Agent: Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)
> Host: www.centos.org
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
......
......

注意屏幕中的 "User-Agent" 一行。

去掉HTTP头信息:

curl 'https://www.centos.org/' -A 'Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)' -o /dev/null
Linux最有意思的地方就是:你永远不知道还有多少黑科技! "/dev/null" 表示将内容写到黑洞,丢东西进去什么事情都不会发生。

9.4.3. 延伸

自定义HTTP头和指定HTTP方法
运行本示例需要可用的网站URL。"http://localhost:9200" 仅做示意,是无法访问的。

默认 curl 使用GET方法请求网站,也可以用 "-X" 指定其它的HTTP方法。

curl -H "Content-Type: application/json" -X POST 'http://localhost:9200/wecompany/employee/2?pretty' -d '
{
    "first_name" :  "Jane",
    "last_name" :   "Smith",
    "age" :         32,
    "about" :       "I like to collect rock albums",
    "interests":  [ "music" ]
}
'
"-H "Content-Type: application/json""

设置HTTP头:Content-Type,表示本次用JSON格式传输请求参数

"-X POST"

指定HTTP方法,向网站服务器发起POST请求

"-d …​"

POST请求的JSON格式参数

9.5. 下载工具(wget)

wget - 功能强大的下载工具,相比 curl 来说功能更加侧重下载。

wget 功能丰富,本文仅介绍基础功能。

9.5.1. 基础用法

URL一定要用一对单引号包住,否则URL中的特殊符合会导致错误。
wget -c url

wget url -O 文件保存位置

wget -c url -O 文件保存位置
常用参数
-c

断点续传下载文件

-O

指定下载文件保存位置,如果文件已经存在则覆盖

-h

帮助信息

9.5.2. 操作演示

断点续传下载文件

下载一个934M的安装镜像文件:

wget http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
屏幕内容
--2021-03-29 13:10:43--  http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
Resolving mirrors.163.com (mirrors.163.com)... 42.186.18.104, 42.186.18.105
Connecting to mirrors.163.com (mirrors.163.com)|42.186.18.104|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1020264448 (973M) [application/octet-stream]
Saving to:CentOS-7-x86_64-Minimal-2009.iso’

 5% [====>                                                           ] 51,857,416  13.7MB/s  eta 60s

下载到约 "1%" 时,按 Ctrl+C 故意停止下载。

查看下载的ISO文件:

ll CentOS-7-x86_64-Minimal-2009.iso*
屏幕内容
-rw-r--r-- 1 root root 52018640 Mar 29 13:10 CentOS-7-x86_64-Minimal-2009.iso

看到 "52018640" 大概已经下载了50M,明显没有下载完。

再执行一次命令,接着下载:

wget http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
屏幕内容
--2021-03-29 13:14:49--  http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
Resolving mirrors.163.com (mirrors.163.com)... 42.186.18.105, 42.186.18.104
Connecting to mirrors.163.com (mirrors.163.com)|42.186.18.105|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1020264448 (973M) [application/octet-stream]
Saving to:CentOS-7-x86_64-Minimal-2009.iso.14% [====>                                                                     ] 44,391,528  16.0MB/s

查看这次下载的ISO文件:

ll CentOS-7-x86_64-Minimal-2009.iso*
屏幕内容
-rw-r--r-- 1 root root 52018640 Mar 29 13:10 CentOS-7-x86_64-Minimal-2009.iso
-rw-r--r-- 1 root root 46634976 Mar 29 13:14 CentOS-7-x86_64-Minimal-2009.iso.1

多了一个 "CentOS-7-x86_64-Minimal-2009.iso.1"

执行了两次 wget 得到两个单独的ISO文件,这不是我们想要的。

“我想断点续传…​…​”

加上 "-c" 表示断点续传:

wget -c http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
屏幕内容
--2021-03-29 13:18:22--  http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
Resolving mirrors.163.com (mirrors.163.com)... 42.186.18.105, 42.186.18.104
Connecting to mirrors.163.com (mirrors.163.com)|42.186.18.105|:80... connected.
HTTP request sent, awaiting response... 206 Partial Content
Length: 1020264448 (973M), 968245808 (923M) remaining [application/octet-stream]
Saving to:CentOS-7-x86_64-Minimal-2009.iso’

12% [+++++========>                                                   ] 123,450,640 11.7MB/s  eta 60s

你可以用 ll 命令看看效果:

ll CentOS-7-x86_64-Minimal-2009.iso*
指定下载文件保存位置,如果文件已经存在则覆盖

下载文件名和保存文件名("CentOS-7-x86_64-Minimal-2009.torrent")相同:

wget http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.torrent -O /tmp/CentOS-7-x86_64-Minimal-2009.torrent

保存为不同的文件名("CentOS7_Minimal.torrent"):

wget http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.torrent -O /tmp/CentOS7_Minimal.torrent
指定下载文件保存位置,如果文件已经存在则断点续传

断点续传方式下载文件 "CentOS-7-x86_64-Minimal-2009.iso ",保存到目录 "/tmp"

wget -c http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso -O /tmp/CentOS-7-x86_64-Minimal-2009.iso
屏幕内容
--2021-03-29 13:38:56--  http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
Resolving mirrors.163.com (mirrors.163.com)... 42.186.18.105, 42.186.18.104
Connecting to mirrors.163.com (mirrors.163.com)|42.186.18.105|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1020264448 (973M) [application/octet-stream]
Saving to: ‘/tmp/CentOS-7-x86_64-Minimal-2009.iso’

14% [================>                                                ] 149,493,656 11.7MB/s  eta 65s
屏幕内容(下载完毕)
--2021-03-29 13:43:15--  http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
Resolving mirrors.163.com (mirrors.163.com)... 42.186.18.105, 42.186.18.104
Connecting to mirrors.163.com (mirrors.163.com)|42.186.18.105|:80... connected.
HTTP request sent, awaiting response... 206 Partial Content
Length: 1020264448 (973M), 942778880 (899M) remaining [application/octet-stream]
Saving to: ‘/tmp/CentOS-7-x86_64-Minimal-2009.iso’

100%[++++++++======================================================>] 1,020,264,448 11.7MB/s   in 76s

2021-03-29 13:44:31 (11.8 MB/s) - ‘/tmp/CentOS-7-x86_64-Minimal-2009.iso’ saved [1020264448/1020264448]
结束之后

删除临时文件:

rm -f /tmp/CentOS-7-x86_64-Minimal-2009.iso* CentOS-7-x86_64-Minimal-2009.iso* /tmp/CentOS-7-x86_64-Minimal-2009.torrent /tmp/CentOS7_Minimal.torrent

9.6. 打印前N行(head)

head - 打印文件的前N行到标准输出

9.6.1. 基础用法

head -n 数量 文件名或路径

命令 | head -n 数量
常用参数
-n

打印前N行。以 '-' 开头时,打印除最后N行以外的所有行。

--help

帮助信息

9.6.2. 操作演示

开始之前

准备演示用的文件:

ls -l / | cat -n > ~/foo.txt
foo.txt内容
     1	total 64
     2	lrwxrwxrwx.  1 root root     7 Feb 15  2019 bin -> usr/bin
     3	dr-xr-xr-x.  5 root root  4096 Aug  9  2019 boot
     4	drwxr-xr-x   5 root root  4096 Aug  1  2019 data
     5	drwxr-xr-x  19 root root  2980 Apr 21  2020 dev
     6	drwxr-xr-x. 91 root root  4096 Jul 11  2020 etc
     7	drwxr-xr-x.  3 root root  4096 Jun 27  2019 home
     8	lrwxrwxrwx.  1 root root     7 Feb 15  2019 lib -> usr/lib
     9	lrwxrwxrwx.  1 root root     9 Feb 15  2019 lib64 -> usr/lib64
    10	drwx------.  2 root root 16384 Feb 15  2019 lost+found
    11	drwxr-xr-x.  2 root root  4096 Apr 11  2018 media
    12	drwxr-xr-x.  2 root root  4096 Apr 11  2018 mnt
    13	drwxr-xr-x.  4 root root  4096 May 13  2019 opt
    14	dr-xr-xr-x  88 root root     0 Apr 12  2020 proc
    15	dr-xr-x---.  9 root root  4096 Feb 19 12:40 root
    16	drwxr-xr-x  25 root root   740 Feb  4 14:08 run
    17	lrwxrwxrwx.  1 root root     8 Feb 15  2019 sbin -> usr/sbin
    18	drwxr-xr-x.  2 root root  4096 Apr 11  2018 srv
    19	dr-xr-xr-x  13 root root     0 Feb 18 10:24 sys
    20	drwxrwxrwt.  8 root root  4096 Feb 19 03:11 tmp
    21	drwxr-xr-x. 13 root root  4096 Feb 15  2019 usr
    22	drwxr-xr-x. 20 root root  4096 May 27  2019 var
打印前14行
head -n 14 ~foo.txt
屏幕内容
     1	total 64
     2	lrwxrwxrwx.  1 root root     7 Feb 15  2019 bin -> usr/bin
     3	dr-xr-xr-x.  5 root root  4096 Aug  9  2019 boot
     4	drwxr-xr-x   5 root root  4096 Aug  1  2019 data
     5	drwxr-xr-x  19 root root  2980 Apr 21  2020 dev
     6	drwxr-xr-x. 91 root root  4096 Jul 11  2020 etc
     7	drwxr-xr-x.  3 root root  4096 Jun 27  2019 home
     8	lrwxrwxrwx.  1 root root     7 Feb 15  2019 lib -> usr/lib
     9	lrwxrwxrwx.  1 root root     9 Feb 15  2019 lib64 -> usr/lib64
    10	drwx------.  2 root root 16384 Feb 15  2019 lost+found
    11	drwxr-xr-x.  2 root root  4096 Apr 11  2018 media
    12	drwxr-xr-x.  2 root root  4096 Apr 11  2018 mnt
    13	drwxr-xr-x.  4 root root  4096 May 13  2019 opt
    14	dr-xr-xr-x  88 root root     0 Apr 12  2020 proc
打印最后8行以外的所有行
head -n -8 ~/foo.txt
屏幕内容
     1	total 64
     2	lrwxrwxrwx.  1 root root     7 Feb 15  2019 bin -> usr/bin
     3	dr-xr-xr-x.  5 root root  4096 Aug  9  2019 boot
     4	drwxr-xr-x   5 root root  4096 Aug  1  2019 data
     5	drwxr-xr-x  19 root root  2980 Apr 21  2020 dev
     6	drwxr-xr-x. 91 root root  4096 Jul 11  2020 etc
     7	drwxr-xr-x.  3 root root  4096 Jun 27  2019 home
     8	lrwxrwxrwx.  1 root root     7 Feb 15  2019 lib -> usr/lib
     9	lrwxrwxrwx.  1 root root     9 Feb 15  2019 lib64 -> usr/lib64
    10	drwx------.  2 root root 16384 Feb 15  2019 lost+found
    11	drwxr-xr-x.  2 root root  4096 Apr 11  2018 media
    12	drwxr-xr-x.  2 root root  4096 Apr 11  2018 mnt
    13	drwxr-xr-x.  4 root root  4096 May 13  2019 opt
    14	dr-xr-xr-x  88 root root     0 Apr 12  2020 proc
foo.txt共22行,"-n 14""-n -8" 得到的结果相同。
打印来自标准输出的前3行
cat ~/foo.txt | head -n 3
屏幕内容
     1	total 64
     2	lrwxrwxrwx.  1 root root     7 Feb 15  2019 bin -> usr/bin
     3	dr-xr-xr-x.  5 root root  4096 Aug  9  2019 boot
结束之后

删除临时文件:

rm -f ~/foo.txt

9.7. 打印后N行(tail)

tail - 打印文件的后N行到标准输出

9.7.1. 基础用法

tail -n 数量 文件名或路径

命令 | tail -n 数量

tail -f 文件名或路径
常用参数
-f

实时滚动刷新,打印新增的数据

-n

打印最后N行。以 '+' 开头时,从第N行开始打印所有行

--help

帮助信息

9.7.2. 操作演示

开始之前

准备演示用的文件:

ls -l / | cat -n > ~/foo.txt
touch ~/bar.txt
foo.txt内容
     1	total 64
     2	lrwxrwxrwx.  1 root root     7 Feb 15  2019 bin -> usr/bin
     3	dr-xr-xr-x.  5 root root  4096 Aug  9  2019 boot
     4	drwxr-xr-x   5 root root  4096 Aug  1  2019 data
     5	drwxr-xr-x  19 root root  2980 Apr 21  2020 dev
     6	drwxr-xr-x. 91 root root  4096 Jul 11  2020 etc
     7	drwxr-xr-x.  3 root root  4096 Jun 27  2019 home
     8	lrwxrwxrwx.  1 root root     7 Feb 15  2019 lib -> usr/lib
     9	lrwxrwxrwx.  1 root root     9 Feb 15  2019 lib64 -> usr/lib64
    10	drwx------.  2 root root 16384 Feb 15  2019 lost+found
    11	drwxr-xr-x.  2 root root  4096 Apr 11  2018 media
    12	drwxr-xr-x.  2 root root  4096 Apr 11  2018 mnt
    13	drwxr-xr-x.  4 root root  4096 May 13  2019 opt
    14	dr-xr-xr-x  88 root root     0 Apr 12  2020 proc
    15	dr-xr-x---.  9 root root  4096 Feb 19 12:40 root
    16	drwxr-xr-x  25 root root   740 Feb  4 14:08 run
    17	lrwxrwxrwx.  1 root root     8 Feb 15  2019 sbin -> usr/sbin
    18	drwxr-xr-x.  2 root root  4096 Apr 11  2018 srv
    19	dr-xr-xr-x  13 root root     0 Feb 18 10:24 sys
    20	drwxrwxrwt.  8 root root  4096 Feb 19 03:11 tmp
    21	drwxr-xr-x. 13 root root  4096 Feb 15  2019 usr
    22	drwxr-xr-x. 20 root root  4096 May 27  2019 var
打印最后10行
tail -n 10 ~/foo.txt
屏幕内容
    13	drwxr-xr-x.  4 root root  4096 May 13  2019 opt
    14	dr-xr-xr-x  88 root root     0 Apr 12  2020 proc
    15	dr-xr-x---.  9 root root  4096 Feb 19 12:40 root
    16	drwxr-xr-x  25 root root   740 Feb  4 14:08 run
    17	lrwxrwxrwx.  1 root root     8 Feb 15  2019 sbin -> usr/sbin
    18	drwxr-xr-x.  2 root root  4096 Apr 11  2018 srv
    19	dr-xr-xr-x  13 root root     0 Feb 18 10:24 sys
    20	drwxrwxrwt.  8 root root  4096 Feb 19 03:11 tmp
    21	drwxr-xr-x. 13 root root  4096 Feb 15  2019 usr
    22	drwxr-xr-x. 20 root root  4096 May 27  2019 var
从第8行开始打印所有行
tail -n +8 ~/foo.txt
屏幕内容
     8	lrwxrwxrwx.  1 root root     7 Feb 15  2019 lib -> usr/lib
     9	lrwxrwxrwx.  1 root root     9 Feb 15  2019 lib64 -> usr/lib64
    10	drwx------.  2 root root 16384 Feb 15  2019 lost+found
    11	drwxr-xr-x.  2 root root  4096 Apr 11  2018 media
    12	drwxr-xr-x.  2 root root  4096 Apr 11  2018 mnt
    13	drwxr-xr-x.  4 root root  4096 May 13  2019 opt
    14	dr-xr-xr-x  88 root root     0 Apr 12  2020 proc
    15	dr-xr-x---.  9 root root  4096 Feb 19 12:40 root
    16	drwxr-xr-x  25 root root   740 Feb  4 14:08 run
    17	lrwxrwxrwx.  1 root root     8 Feb 15  2019 sbin -> usr/sbin
    18	drwxr-xr-x.  2 root root  4096 Apr 11  2018 srv
    19	dr-xr-xr-x  13 root root     0 Feb 18 10:24 sys
    20	drwxrwxrwt.  8 root root  4096 Feb 19 03:11 tmp
    21	drwxr-xr-x. 13 root root  4096 Feb 15  2019 usr
    22	drwxr-xr-x. 20 root root  4096 May 27  2019 var
打印来自标准输出的最后5行
cat ~/foo.txt | tail -n 5
屏幕内容
    18	drwxr-xr-x.  2 root root  4096 Apr 11  2018 srv
    19	dr-xr-xr-x  13 root root     0 Feb 18 10:24 sys
    20	drwxrwxrwt.  8 root root  4096 Feb 19 03:11 tmp
    21	drwxr-xr-x. 13 root root  4096 Feb 15  2019 usr
    22	drwxr-xr-x. 20 root root  4096 May 27  2019 var
实时滚动刷新
本示例会用到两个终端。
终端1
tail -f ~/bar.txt

这时终端1的屏幕上没有任何内容显示。

终端1保持打开状态,不要关闭

保持终端1和终端2,在终端2中反复执行以下命令:

终端2
echo `date "+%Y.%m.%d %M:%H:%S.%N"` >> ~/bar.txt

在终端2中反复执行3次命令后,终端1的屏幕内容结果如下:

第1次
2021.02.19 18:13:23.935206258
第2次
2021.02.19 18:13:23.935206258
2021.02.19 18:13:25.647371570
第3次
2021.02.19 18:13:23.935206258
2021.02.19 18:13:25.647371570
2021.02.19 18:13:26.607005345

可以看到终端1的屏幕内容一直在实时滚动刷新。

tail -f access.log 在查看网站访问日志记录时非常实用。
结束之后

删除临时文件:

rm -f ~/foo.txt ~/bar.txt

9.8. 打印到标准输出(cat)

cat - 打印一个或多个文件的内容到标准输出

9.8.1. 基础用法

cat 文件名或路径

cat 文件名或路径 | 命令
常用参数
-n

在行首添加行序号

--help

帮助信息

9.8.2. 操作演示

开始之前

创建演示文件

echo 'foo.line1' > ~/foo.txt
echo 'foo.line2' >> ~/foo.txt

echo 'bar.line1' > ~/bar.txt
echo 'bar.line2' >> ~/bar.txt
打印文件内容
cat ~/foo.txt ~/bar.txt
屏幕内容
foo.line1
foo.line2
bar.line1
bar.line2
打印时加上序号
cat -n ~/foo.txt ~/bar.txt
屏幕内容
     1	foo.line1
     2	foo.line2
     3	bar.line1
     4	bar.line2
延伸:打印并排序文件内容
cat ~/foo.txt ~/bar.txt | sort
屏幕内容
bar.line1
bar.line2
foo.line1
foo.line2
结束之后

删除临时文件:

rm -f ~/foo.txt ~/bar.txt

9.9. 打印第N列(cut)

cut - 将行转为列,将指定列打印到标准输出

在Linux中处理数据时,分列和管道操作简直就是银弹,无敌的存在~

9.9.1. 基础用法

cut -d '分隔符' -f 列号 文件名或路径

命令 | cut -d '分隔符' -f 列号
常用参数
-d

列分隔符

-f

选中的列号列表,可以同时打印多列

--help

帮助信息

9.9.2. 操作演示

在前面讲管道的章节,演示过复杂的命令:

ps aux | tail -n +2 | cut -d ' ' -f 1 | sort -u

“有没有简单又形象的例子”

“往下看…​…​”

开始之前

网站日志分析是家常便饭,准备一些简化后的日志记录:

cat << EOF > ~/access.log
foo.com 80 118.118.47.239 [18/Feb/2021:23:22:23] "GET /360.html HTTP/1.1" 200
foo.com 80 115.202.80.105 [18/Feb/2021:23:22:24] "GET /login HTTP/1.1" 200
foo.com 80 123.6.49.36 [18/Feb/2021:23:22:24] "GET / HTTP/1.1" 200
foo.com 80 180.101.214.20 [18/Feb/2021:23:22:24] "GET /main.html HTTP/1.1" 200
foo.com 80 180.101.52.35 [18/Feb/2021:23:22:24] "GET /jquery.min.js HTTP/1.1" 200
foo.com 80 148.72.153.60 [18/Feb/2021:23:25:16] "GET /7.html HTTP/1.1" 200
foo.com 80 123.178.50.195 [18/Feb/2021:23:25:16] "GET /article/ HTTP/1.1" 200
EOF

仔细观察,看起来用空格分列就行了,试试~

打印日志记录的第1列
cut -d ' ' -f 1 ~/access.log
屏幕内容
foo.com
foo.com
foo.com
foo.com
foo.com
foo.com
foo.com
打印日志记录的第1/3/5列
cut -d ' ' -f 1,3,5 ~/access.log
屏幕内容
foo.com 118.118.47.239 "GET
foo.com 115.202.80.105 "GET
foo.com 123.6.49.36 "GET
foo.com 180.101.214.20 "GET
foo.com 180.101.52.35 "GET
foo.com 148.72.153.60 "GET
foo.com 123.178.50.195 "GET
打印日志记录的第3至4列
cut -d ' ' -f 3-4 ~/access.log
屏幕内容
118.118.47.239 [18/Feb/2021:23:22:23]
115.202.80.105 [18/Feb/2021:23:22:24]
123.6.49.36 [18/Feb/2021:23:22:24]
180.101.214.20 [18/Feb/2021:23:22:24]
180.101.52.35 [18/Feb/2021:23:22:24]
148.72.153.60 [18/Feb/2021:23:25:16]
123.178.50.195 [18/Feb/2021:23:25:16]
打印日志记录的第1至5列
cut -d ' ' -f -5 ~/access.log
屏幕内容
foo.com 80 118.118.47.239 [18/Feb/2021:23:22:23] "GET
foo.com 80 115.202.80.105 [18/Feb/2021:23:22:24] "GET
foo.com 80 123.6.49.36 [18/Feb/2021:23:22:24] "GET
foo.com 80 180.101.214.20 [18/Feb/2021:23:22:24] "GET
foo.com 80 180.101.52.35 [18/Feb/2021:23:22:24] "GET
foo.com 80 148.72.153.60 [18/Feb/2021:23:25:16] "GET
foo.com 80 123.178.50.195 [18/Feb/2021:23:25:16] "GET
打印日志记录的第5至最后1列
cut -d ' ' -f 5- ~/access.log
屏幕内容
"GET /360.html HTTP/1.1" 200
"GET /login HTTP/1.1" 200
"GET / HTTP/1.1" 200
"GET /main.html HTTP/1.1" 200
"GET /jquery.min.js HTTP/1.1" 200
"GET /7.html HTTP/1.1" 200
"GET /article/ HTTP/1.1" 200
结束之后

删除临时文件:

rm -f ~/access.log

9.10. 显示当前进程(ps)

ps - 显示当前运行的进程列表,常用于系统或程序排错

ps 命令功能强大、参数组合丰富,本文仅介绍基础功能。
作为了解系统运行状态的重要工具,pstop 命令经常搭配使用。

9.10.1. 基础用法

ps -ef

ps -ef | grep python
常用参数
-e

列出所有进程

-f

显示进程命令行参数

--help all

帮助信息

9.10.2. 操作演示

列出所有进程
ps -ef
屏幕内容
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0  2020 ?        01:10:11 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root         2     0  0  2020 ?        00:00:00 [kthreadd]
root         3     2  0  2020 ?        00:14:11 [ksoftirqd/0]
root         5     2  0  2020 ?        00:00:00 [kworker/0:0H]
root         7     2  0  2020 ?        00:00:00 [migration/0]
root         8     2  0  2020 ?        00:00:00 [rcu_bh]
root         9     2  0  2020 ?        00:14:37 [rcu_sched]
root        10     2  0  2020 ?        00:00:00 [lru-add-drain]
root        11     2  0  2020 ?        00:03:14 [watchdog/0]
root        13     2  0  2020 ?        00:00:00 [kdevtmpfs]
root        14     2  0  2020 ?        00:00:00 [netns]
root        15     2  0  2020 ?        00:00:10 [khungtaskd]
......
过滤进程

ps 参数很多,不建议深入了解。直接用 grep 命令过滤输出结果为上策。

从输出结果中,找出包含 "python" 关键字的进程:

ps -ef | grep python
屏幕内容
root       941     1  0  2020 ?        01:05:04 /usr/bin/python2 -Es /usr/sbin/tuned -l -P
root     31798 30406  0 15:17 pts/0    00:00:00 grep --color=auto python
root     32050 31982  0  2020 ?        00:00:00 /opt/eff.org/certbot/venv/bin/python /tmp/tmp.VxCfwAqjDj/pipstrap.py
ps -ef | grep python | grep -v 'grep' 可以过滤掉多余的 grep

9.11. 文本替换(sed)

sed - 基于行的,用来过滤和转换文本的流编辑工具

sed 常用来替换每行中指定的字符串,非常方便。

其它功能不做介绍。

9.11.1. 基础用法

sed -i 's/old text/new text/g' 文件路径
常用参数
-i

修改文件,不使用该参数时修改的内容会直接打印到屏幕

s///g

"s" 表示替换动作,"g" 表示替换所有(否则,仅替换一次)

--help

帮助信息

9.11.2. 操作演示

开始之前
创建演示文件
cat << EOF > ~/word.txt
1,foobar
2,foo
3,qux
4,quux
5,quuz
EOF

为便于演示,以下操作移除了 -i 参数。实际使用过程中,用 sed -i 直接修改文件内容。

将每行中第1个 "u" 替换为 "U"
sed 's/u/U/' word.txt
屏幕内容
1,foobar
2,foo
3,qUx
4,qUux
5,qUuz
替换所有 "u""U"
sed 's/u/U/g' word.txt
屏幕内容
1,foobar
2,foo
3,qUx
4,qUUx
5,qUUz
替换文 "qux""QUX"
sed 's/qux/QUX/g' word.txt
屏幕内容
1,foobar
2,foo
3,QUX
4,quux
5,quuz
替换长度至少为3,并且以 "q" 开头的文本
sed 's/q../+++/g' word.txt
屏幕内容
1,foobar
2,foo
3,+++
4,+++x
5,+++z
替换 "5" 开头,"z" 结尾的文本
sed 's/^5.*z/+/g' word.txt
屏幕内容
1,foobar
2,foo
3,qux
4,quux
+
结束之后

删除临时文件:

rm -f ~/word.txt

9.12. 列数据组合(awk)

awk - 基于行的,文本模式扫描和处理的迷你编程语言

常用 awk 将行数据分列组合,可生成新的数据结果。相比其它类似命令(如,sed / cut),awk 更侧重列数据间的组合和拼接。

同样,awk 本文仅介绍基本用法。

不要尝试用 awk 完成复杂任务,用 Python 处理更加明智。

9.12.1. 基础用法

awk '{print $NF}' 文件路径

awk -F  ':' '{print $1 " - " $(NF-1) " - " $NF}' 文件路径
常用参数
-F

列分隔符,默认以空格分列

{ action }

执行的动作

print

打印数据到屏幕

" - "

中横线以及前后两个空格

$1

行数据的第一列

$(NF-1)

行数据的倒数第二列

$NF

行数据的最后一列

--help

帮助信息

9.12.2. 操作演示

开始之前
创建演示文件
head -n 10 /etc/group > ~/group.txt
打印第一列
awk -F ':' '{print $1}' ~/group.txt
屏幕内容
root
bin
daemon
sys
adm
tty
disk
lp
mem
kmem
打印最后一列
awk -F ':' '{print $NF}' ~/group.txt
屏幕内容
(空)
(空)
(空)
(空)
(空)
(空)
(空)
(空)
(空)
(空)
打印倒数第二列
awk -F ':' '{print $(NF-1)}' ~/group.txt
屏幕内容
0
1
2
3
4
5
6
7
8
9
打印指定列,并用中横线分隔
awk -F  ':' '{print $(NF-1) " - " $1}' ~/group.txt
屏幕内容
0 - root
1 - bin
2 - daemon
3 - sys
4 - adm
5 - tty
6 - disk
7 - lp
8 - mem
9 - kmem
结束之后

删除临时文件:

rm -f ~/group.txt

9.13. 查看内存(free)

free - 显示系统内存信息

9.13.1. 基础用法

free -h

free -m
常用参数
-h

以人类友好格式显示内存信息

-m

以Mib为单位显示内存信息

--help

帮助信息

输出说明
total

可用内存总量

used

已经分配的内存(计算方式: "total" - "free" - "buff/cache"

free

未分配的内存

shared

(可忽略,无实际意义)

buff/cache

内核缓冲区、页面缓存和slab使用的内存数,必要时会分配给应用程序使用

available

应用程序可直接使用的内存数(估计)

Linux还剩多少内存可以给应用程序使用?

理想状态下,等于 "free" + "buff/cache"(实际中的数据有较大的误差)。

9.13.2. 操作演示

人类友好格式显示
free -h
屏幕内容
              total        used        free      shared  buff/cache   available
Mem:            23G         13G        214M         88M        9.8G        9.5G
Swap:           38G        1.2G         37G
Mib为单位显示
free -m
屏幕内容
              total        used        free      shared  buff/cache   available
Mem:          24066       13850         210          88       10005        9764
Swap:         39396        1274       38122

9.14. 查看硬盘空间(df)

df - 显示文件系统硬盘空间使用量

9.14.1. 基础用法

df -h

df -hT
常用参数
-h

以人类友好格式显示硬盘使用量

-T

打印文件系统类型

--help

帮助信息

输出说明
Filesystem

存储设备或文件系统,通常指硬盘设备、硬盘分区、网络硬盘设备、系统设备等

Type

存储设备的文件系统类型,如ext4、xfs等

Size

设备或分区总容量

Used

已用容量

Avail

可用容量

Use%

已用容量百分比

Mounted on

挂载点

操作演示

人类友好格式显示
df -h
屏幕内容
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   34G  4.0G  90% /
devtmpfs        486M     0  486M   0% /dev
tmpfs           496M     0  496M   0% /dev/shm
tmpfs           496M  472K  496M   1% /run
tmpfs           496M     0  496M   0% /sys/fs/cgroup
tmpfs           100M     0  100M   0% /run/user/0
显示文件系统类型
df -hT
屏幕内容
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/vda1      ext4       40G   34G  4.0G  90% /
devtmpfs       devtmpfs  486M     0  486M   0% /dev
tmpfs          tmpfs     496M     0  496M   0% /dev/shm
tmpfs          tmpfs     496M  472K  496M   1% /run
tmpfs          tmpfs     496M     0  496M   0% /sys/fs/cgroup
tmpfs          tmpfs     100M     0  100M   0% /run/user/0

9.15. 文件格式转换(dos2unix)

dos2unix - 用于将Windows格式的纯文本文件转为Linux格式

unix2dos - 用于将Linux格式的纯文本文件转为Windows格式

以上两个命令常用于转换回车符(CR)和换行符(LF)互转。

Linux的文本文件中,换行符由单个换行符(LF)表示("\n")。

而Windows的文本文件中,换行符则由回车符(CR)和单个换行符(LF)表示("\r\n")。

9.15.1. 安装

yum install -y dos2unix unix2dos

9.15.2. 基础用法

dos2unix 文件路径

unix2dos 文件路径

无常用参数。

9.15.3. 操作演示

开始之前
创建演示文件
echo -ne "Hello\r\nWorld\r\n" > ~/foo.txt
确认文件格式
file ~/foo.txt
屏幕内容
foo.txt: ASCII text, with CRLF line terminators

"CRLF" 表示文件使用 "\r\n" 换行。

转为Linux格式
dos2unix ~/foo.txt
屏幕内容
dos2unix: converting file /root/foo.txt to Unix format ...
确认文件格式
file ~/foo.txt
屏幕内容
/root/foo.txt: ASCII text
转为Windows格式
unix2dos ~/foo.txt
屏幕内容
unix2dos: converting file /root/foo.txt to DOS format ...
确认文件格式
file ~/foo.txt
屏幕内容
/root/foo.txt: ASCII text, with CRLF line terminators
结束之后

删除临时文件:

rm -f ~/foo.txt

9.16. 显示命令路径(which)

which - 显示指定命令的完整路径

9.16.1. 基础用法

which 命令名称

无常用参数。

9.16.2. 操作演示

显示 ls 命令的路径
which ls
屏幕内容
alias ls='ls --color=auto'
	/usr/bin/ls
显示 ll 命令的路径
which ll
屏幕内容
alias ll='ls -l --color=auto'
	/usr/bin/ls
显示 mkdir 命令的路径
which mkdir
屏幕内容
/usr/bin/mkdir
显示 sshd 命令的路径
which sshd
屏幕内容
/usr/sbin/sshd

10. 内容搜索

10.1. 简介

前面已经提到过管道、cutawksedsort 等等命令。

还没来得及最受欢迎的 grep 命令。grep 可以过滤出想要的字符串,也就是一个字符串搜索工具。

grep 、管道以及其它命令结合在一起时,可以大大提升使用Linux的幸福感。

10.2. 基础用法

10.2.1. 一个简单示例

搜索文件中的某个字符串,指定搜索关键字和文件名即可:

grep mail /etc/passwd
屏幕内容
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

10.2.2. 忽略大小写

grep -i crond /var/log/cron
屏幕内容
May 23 03:50:01 cdgeekcamp CROND[6603]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 04:00:01 cdgeekcamp CROND[6610]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 04:01:01 cdgeekcamp CROND[6617]: (root) CMD (run-parts /etc/cron.hourly)
May 23 04:10:01 cdgeekcamp CROND[6630]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 04:20:01 cdgeekcamp CROND[6638]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 04:30:01 cdgeekcamp CROND[6645]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 04:40:01 cdgeekcamp CROND[6652]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 04:50:01 cdgeekcamp CROND[6660]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 05:00:01 cdgeekcamp CROND[6669]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 05:01:01 cdgeekcamp CROND[6676]: (root) CMD (run-parts /etc/cron.hourly)

10.2.3. 反向匹配

grep -v 'run-parts /etc/cron.hourly' /var/log/cron
关键字包含空格时,必须用单引号或双引号包起来。
屏幕内容
May 23 03:42:01 cdgeekcamp run-parts(/etc/cron.daily)[6576]: finished logrotate
May 23 03:42:01 cdgeekcamp run-parts(/etc/cron.daily)[6559]: starting man-db.cron
May 23 03:42:01 cdgeekcamp run-parts(/etc/cron.daily)[6587]: finished man-db.cron
May 23 03:42:01 cdgeekcamp run-parts(/etc/cron.daily)[6559]: starting mlocate
May 23 03:42:01 cdgeekcamp run-parts(/etc/cron.daily)[6598]: finished mlocate
May 23 03:42:01 cdgeekcamp anacron[6534]: Job `cron.daily' terminated
May 23 03:42:01 cdgeekcamp anacron[6534]: Normal exit (1 job run)
May 23 03:50:01 cdgeekcamp CROND[6603]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 04:00:01 cdgeekcamp CROND[6610]: (root) CMD (/usr/lib64/sa/sa1 1 1)
May 23 04:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6617]: starting 0anacron
May 23 04:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6626]: finished 0anacron

10.3. 搜索目录下文件的内容

grep -r -i crond /var/log/

grep -ri crond /var/log/
屏幕内容
/var/log/cron-20210509:May  2 03:10:01 cdgeekcamp CROND[22917]: (root) CMD (/usr/lib64/sa/sa1 1 1)
/var/log/cron-20210509:May  2 03:20:01 cdgeekcamp CROND[23403]: (root) CMD (/usr/lib64/sa/sa1 1 1)
/var/log/cron-20210509:May  2 03:30:01 cdgeekcamp CROND[23889]: (root) CMD (/usr/lib64/sa/sa1 1 1)
/var/log/cron-20210509:May  2 03:40:01 cdgeekcamp CROND[24375]: (root) CMD (/usr/lib64/sa/sa1 1 1)
/var/log/cron-20210509:May  2 03:50:01 cdgeekcamp CROND[24862]: (root) CMD (/usr/lib64/sa/sa1 1 1)
......
/var/log/audit/audit.log.1:type=USER_ACCT msg=audit(1620024001.562:647420): pid=29877 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:accounting grantors=pam_access,pam_unix,pam_localuser acct="root" exe="/usr/sbin/crond" hostname=? addr=? terminal=cron res=success'
/var/log/audit/audit.log.1:type=CRED_ACQ msg=audit(1620024001.562:647421): pid=29877 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:setcred grantors=pam_env,pam_unix acct="root" exe="/usr/sbin/crond" hostname=? addr=? terminal=cron res=success'

10.4. 搜索结果计数

grep 能做搜索过滤,还可以输出数字或计数信息。

10.4.1. 统计文本在文件中出现多少次

grep -c cron.hourly /var/log/cron
屏幕内容
318

文本 "cron.hourly" 在文件中出现 "318" 次。

10.4.2. 打印行号

grep -n cron.hourly /var/log/cron
屏幕内容
10:May 23 04:01:01 cdgeekcamp CROND[6617]: (root) CMD (run-parts /etc/cron.hourly)
11:May 23 04:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6617]: starting 0anacron
12:May 23 04:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6626]: finished 0anacron
19:May 23 05:01:01 cdgeekcamp CROND[6676]: (root) CMD (run-parts /etc/cron.hourly)
20:May 23 05:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6676]: starting 0anacron
21:May 23 05:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6685]: finished 0anacron
28:May 23 06:01:01 cdgeekcamp CROND[6733]: (root) CMD (run-parts /etc/cron.hourly)
29:May 23 06:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6733]: starting 0anacron
30:May 23 06:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6742]: finished 0anacron
......(省略部分内容)

每行的第一个数字表示行号。

10.4.3. 打印前N行内容,带上行号

打印前5行结果:

grep -n -m 5 cron.hourly /var/log/cron
屏幕内容
10:May 23 04:01:01 cdgeekcamp CROND[6617]: (root) CMD (run-parts /etc/cron.hourly)
11:May 23 04:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6617]: starting 0anacron
12:May 23 04:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6626]: finished 0anacron
19:May 23 05:01:01 cdgeekcamp CROND[6676]: (root) CMD (run-parts /etc/cron.hourly)
20:May 23 05:01:01 cdgeekcamp run-parts(/etc/cron.hourly)[6676]: starting 0anacron

10.5. 输出匹配位置的上下内容

想看看搜索关键字前后的内容,用 "-A""-B""-C" 三个选项就行。

10.5.1. "/etc/passwd" 文件部分内容

/etc/passwd部分内容
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin

在开始之前,留意下

nobody:x:99:99:Nobody:/:/sbin/nologin

前后的内容。

10.5.2. 打印匹配文本的行及其前面N行

找出包含 "nobody:" 的行,同时匹配行的前2行内容(共3行):

grep -B 2 'nobody:' /etc/passwd
屏幕内容
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin

10.5.3. 打印匹配文本的行及其后面N行

找出包含 "nobody:" 的行,同时匹配行的后2行内容(共3行):

grep -A 2 'nobody:' /etc/passwd
屏幕内容
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin

10.5.4. 打印匹配文本的行及其前后N行

找出包含 "nobody:" 的行,同时匹配行的前后2行内容(共5行):

grep -C 2 'nobody:' /etc/passwd
屏幕内容
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin

10.6. 使用正则表达式

现在你对 grep 的了解已经可以应付大多数情况,搜索关键字、搜索目录下的内容、结果计数甚至显示结果前后内容都不在话下。

这些都是在关键字明确的前提下。万一某天想搜索关键字的一部分,你该怎么做?又或者,需要更加复杂的搜索操作呢?

grep 结合正则表达式(grep -E)做搜索,就完事儿。

习惯简写成 egrep

10.6.1. 行首行尾匹配

打印以字母 "n" 开头的行:

grep '^n' /etc/passwd
屏幕内容
nobody:x:99:99:Nobody:/:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
nginx:x:997:995:nginx user:/var/cache/nginx:/sbin/nologin

打印以字母 "h" 结尾的行:

grep 'h$' /etc/passwd
屏幕内容
root:x:0:0:root:/root:/bin/bash
www:x:1001:1001::/var/lib/www:/bin/bash

10.6.2. 字符串匹配

打印以字母 "t" 开头,字母 "n" 结尾的行:

egrep '^t.*n$' /etc/passwd
屏幕内容
tcpdump:x:72:72::/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
tomcat:x:53:53:Apache Tomcat:/usr/share/tomcat:/sbin/nologin

10.6.3. egrep 支持的正则表达式

一点点准备

创建一个测试数据文件:

cat << EOF > ~/access.log
foo.org 80 118.118.47.239 [18/Jan/2021:01:00:23] "GET /360.html HTTP/1.1" 200
bar.org 8080 115.202.80.105 [19/Feb/2021:02:12:24] "POST /login HTTP/1.1" 404
qux.com 80 123.6.49.36 [20/Mar/2021:03:22:24] "GET / HTTP/1.1" 200
quux.com 80 180.101.214.20 [21/Apr/2021:04:15:24] "GET /main.html HTTP/1.1" 200
quz.io 8080 180.101.52.35 [21/Aug/2021:13:18:24] "GET /log.jpg HTTP/1.1" 200
quuz.cn 8080 180.101.52.35 [21/Aug/2021:13:18:24] "GET /jquery.min.js HTTP/1.1" 403
quuuz.cn 8080 125.64.14.56 [21/Aug/2021:13:18:24] "GET /load.js HTTP/1.1" 200
corge.com 80 148.72.153.60 [22/May/2021:23:25:16] "GET /7.html HTTP/1.1" 500
garply.net 80 123.178.50.195 [23/Oct/2021:23:50:16] "POST /article/ HTTP/1.1" 301
garply.net 80 123.178.50.195 [23/Oct/2021:23:50:16] "POST /article_new/ HTTP/1.1" 200
EOF
在下文看到 egrep '正则表达式' ~/access.log 这样的命令时,复制到终端试一试。动手效果更好!

基础操作符

小原点 '.' 用作正则表达式符号时,表示匹配任意字符,'b''x''0' 等等都没问题。


匹配常见字符串是最基础的正则表达式,如 aa0.?.{1,2} 等等。


大部分字符(包括大小写字母、数字)作表达式都表示自身(所见即所得)。比如,0 匹配数字零,aa 匹配两个小写字母a。


a. 能够匹配长度为2的行,第一个字符必须是小写字母 'a',第二个可以是任意字符,'a1''ab''a,' 都符合规则。


只匹配一个小写字母a和一个小原点('a.')则用 a\.\. 表示一个小原点本身。相反,. 表示匹配任意字符。


也就是说,表达式符号前多加一个斜杠表示字符本身,称作字符转义。


以下操作符号可以限定在匹配时,某个字符可以出现多少次:

操作符 说明 示例

?

匹配0次或1次

匹配包含 'quu' 的行

egrep 'quu.?' ~/access.log

匹配包含 'qu' 和 'qux' 的行

egrep 'qux?' ~/access.log

*

匹配0次或多次

匹配包含 'GET'、'500' 的行

egrep 'GET.*500' ~/access.log

匹配包含 'article_' 和 'article' 的行

egrep 'article_*' ~/access.log

+

匹配至少1次

匹配包含 'article' 的行

egrep 'article.+' ~/access.log

匹配包含 'article_' 的行

egrep 'article_+' ~/access.log

{n}

只匹配n次

匹配包含 'qux' 的行

egrep 'qux{1}' ~/access.log

匹配至少包含一个 'q' 和两个 '0' 的行

egrep 'q{1}.*0{2}' ~/access.log

{n,}

匹配至少n次

匹配包含 'quu' 的行

egrep 'qu{2,}' ~/access.log

{,m}

匹配最多m次

匹配包含 'quz' 和 'quuz' 的行

egrep 'qu{,2}z' ~/access.log

{n,m}

匹配至少n次,最多m次

匹配包含 'quuz' 和 'quuuz' 的行

egrep 'qu{2,3}z' ~/access.log

上面这些单表达式匹配的例子挺OK的,那同时找出包含 'article_' 和 'qux' 的行怎么做?

一个中竖线和一对圆括号连接多个表达式,轻松完成多表达式查找匹配:

egrep '(article_+)|(qux)' ~/access.log
屏幕内容
qux.com 80 123.6.49.36 [20/Mar/2021:03:22:24] "GET / HTTP/1.1" 200
garply.net 80 123.178.50.195 [23/Oct/2021:23:50:16] "POST /article_new/ HTTP/1.1" 200
| 前后不能有空格。

更多 egrep 支持的正则表达式内容,请阅读 egrep正则表达式扩展


egrep 支持的缩写

一个斜杠后紧跟某些普通字符时,具有特殊的含义:

\w

匹配英文单词,通常单词由下划线、大小写字母和数字组成,等同 [_[:alnum:]]

egrep '\w' ~/access.log

\W

匹配非英文单词,也就是匹配下划线、大小写字母和数字以外的字符,等同 [^_[:alnum:]]

egrep '\W' ~/access.log

\s

匹配空格, 等同 [[:space:]]

egrep '\s' ~/access.log

\S

匹配非空格, 等同 [^[:space:]]

egrep '\S' ~/access.log

动动手,练习一个多表达式的例子:

egrep '\w+\s' ~/access.log

匹配至少一个英文单词字符,并且紧跟一个空格的行。你会看到类似这样的输出结果:

garply.net 80 123.178.50.195 [23/Oct/2021:23:50:16] "POST /article_new/ HTTP/1.1" 200


egrep 的限制

egrep 的在功能实现时,对特定的表达式有限制。

会经常遇到中横线开头的表达式提示有错误,错误示范如下:

egrep '-foo' ~/access.log
错误提示
grep: oo: No such file or directory

正确的示范:

egrep '\-foo' ~/access.log

记住,表达式不能用中横线(-)开头,必须加转义后才行。

更多其它的限制,万年遇不到,直接略过~

10.7. grep和管道

Linux的两大神技 grep 和管道结合,才是使用频率最高的。

看看这个例子:

grep 'Accepted' /var/log/secure | cut -d ' ' -f 9,11 | sort -u
屏幕内容
git 171.221.150.93
git 182.138.181.132
root 171.221.150.93
root 182.138.181.132

换个写法:

cat /var/log/secure | grep 'Accepted' | cut -d ' ' -f 9,11 | sort -u

输出结果和上面是一样的。


再来一个新花样:

cat /var/log/secure | grep 'Accepted' | awk '{print "User:"$9", Login IP address:"$11}' | sort -u

或

cat /var/log/secure | egrep 'Accep\w+' | awk '{print "User:"$9", Login IP address:"$11}' | sort -u
屏幕内容
User:git, Login IP address:171.221.150.93
User:git, Login IP address:182.138.181.132
User:root, Login IP address:171.221.150.93
User:root, Login IP address:182.138.181.132

grep 可以直接查找文件中的内容,也可以直接查找管道前面(标准输出)的内容。

再结合 "-rni" 之类的参数, 让 grep 变成几乎万能的文件内容查找工具。

用过的人都说好!

11. 文件定位

11.1. 简介

安装软件后,怎么快速找出配置文件路径?
想不起自己安装的软件到哪儿去了?

不需要复杂的操作,用 locatefind 命令几秒钟解决文件搜索问题。

locate 在文件索引(不需要实时读取目录)中搜索指定文件名,搜索速度很快。Windows软件 Everythinglocate 功能实现非常类似。

find 实时搜索指定目录中的文件名,搜索速度取决于硬盘速度。

两个命令用途相似,明确要查找某个目录下的文件时用 find,其它情况建议无脑 locate

11.2. locate

locate 命令是软件 mlocate 的一部分,locate 在文件索引中搜索指定文件名。

mlocate 还有一个 updatedb 命令,负责更新文件索引。

11.2.1. 安装mlocate

安装mlocate软件包:

yum install -y mlocate

首次更新文件索引:

updatedb

默认情况下,CentOS计划任务会每天自动更新一次(执行一次 updatedb 命令)文件索引。

如果当前新安装了软件或上传了文件到CentOS,需要手动执行 updatedb。然后,locate 才能找到新文件。

在增加文件、删除文件后,使用 locate 前记得先 updatedb

P.S. updatedb 可以执行无数次,不要有心理负担~

11.2.2. 示例

搜索包含 "linux""signal.h" 关键字的文件路径:

示例1
locate signal.h | grep linux
屏幕内容
/usr/include/linux/signal.h

搜索ssh服务相关的配置文件路径(必须同时包含 "config""etc"):

示例2
locate -b ssh | grep config | grep etc
屏幕内容
/etc/ssh/ssh_config
/etc/ssh/sshd_config
/etc/sysconfig/sshd

-b 参数表示只搜索文件名部分(如 "ssh_config""sshd_config""sshd" 等等),不搜索路径中的字符串。


用正则表达式搜索所有日志文件(以 ".log" 扩展名结尾的文件路径):

示例3
locate -r '\.log$'
屏幕内容
/usr/lib/rpm/rpm.log
/var/log/boot.log
/var/log/mysqld.log
/var/log/yum.log
/var/log/audit/audit.log
......

-r 参数表示使用正则表达式搜索,注意必须用单引号包住表达式。


搜索 "ssh" 相关的 "service" 文件:

示例4
locate .service | grep ssh

或

locate -r 'ssh.*service'
屏幕内容
/etc/systemd/system/multi-user.target.wants/sshd.service
/usr/lib/systemd/system/sshd-keygen.service
/usr/lib/systemd/system/sshd.service
/usr/lib/systemd/system/sshd@.service

11.3. find

find 命令属于系统自带的,不需要安装。

为和 locate 对比,以下示例和之前相同。

注意对比 find 命令和 locate 的执行速度。

11.3.1. 示例

搜索包含 "linux""signal.h" 关键字的文件路径:

示例1
find / | grep signal.h | grep linux
屏幕内容
/usr/include/linux/signal.h

搜索ssh服务相关的配置文件路径(必须同时包含 "config""etc"):

示例2
find / | grep ssh | grep config | grep etc
屏幕内容
/etc/ssh/ssh_config
/etc/ssh/sshd_config
/etc/sysconfig/sshd

用正则表达式搜索所有日志文件(以 ".log" 扩展名结尾的文件路径):

示例3
find / -name '*.log'
屏幕内容
/usr/lib/rpm/rpm.log
/var/log/boot.log
/var/log/mysqld.log
/var/log/yum.log
/var/log/audit/audit.log
......

-name 参数表示只搜索文件名部分(如 "rpm.log""boot.log" 等等),不搜索路径中的字符串。


搜索 "ssh" 相关的 "service" 文件:

示例4
find / -name '*.service' | grep ssh
屏幕内容
/sys/fs/cgroup/systemd/system.slice/sshd.service
/etc/systemd/system/multi-user.target.wants/sshd.service
/usr/lib/systemd/system/sshd@.service
/usr/lib/systemd/system/sshd.service
/usr/lib/systemd/system/sshd-keygen.service

上面的

/sys/fs/cgroup/systemd/system.slice/sshd.service

locate 是不会有的。因为 locate 会忽略类似 "/tmp""/proc""/sys" 之类的系统临时目录。

12. 软件包管理

12.1. 简介

yum是基于RPM的包管理器( ".rpm" 格式文件),可以从网络仓库查询、下载软件包,安装并升级系统至最新版。当然,移除软件包也是可以的。

yum会扫描软件的依赖关系,自动检测、下载并安装相关软件。不需要搜索官网下载软件安装包,不需要手动解决软件安装环境依赖。

yum可以配置外部(网络软件)仓库或源代码仓库,提供许多内置插件来增强和扩展功能。比如,增加第三方仓库、启用禁用仓库、设置网络代理等。

12.2. 安装

12.2.1. 基础用法

yum install -y 软件包名称或路径
常用参数
y

表示 yum 全自动执行(不交互回答问题)

12.2.2. 从仓库安装

yum install -y tree
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package tree.x86_64 0:1.6.0-10.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=========================================================
 Package   Arch    Version        Repository         Size
=========================================================
Installing:
 tree      x86_64  1.6.0-10.el7   base               46 k

Transaction Summary
=========================================================
Install  1 Package

Total download size: 46 k
Installed size: 87 k
Downloading packages:
tree-1.6.0-10.el7.x86_64.rpm           |  46 kB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : tree-1.6.0-10.el7.x86_64               1/1
  Verifying  : tree-1.6.0-10.el7.x86_64               1/1

Installed:
  tree.x86_64 0:1.6.0-10.el7

Complete!

12.2.3. 从URL安装

yum install -y https://mirrors.163.com/centos/7/os/x86_64/Packages/tree-1.6.0-10.el7.x86_64.rpm
屏幕内容
Loaded plugins: fastestmirror
tree-1.6.0-10.el7.x86_64.rpm                                           |  46 kB  00:00:00
Examining /var/tmp/yum-root-kombYG/tree-1.6.0-10.el7.x86_64.rpm: tree-1.6.0-10.el7.x86_64
Marking /var/tmp/yum-root-kombYG/tree-1.6.0-10.el7.x86_64.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package tree.x86_64 0:1.6.0-10.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=========================================================================================
 Package     Arch       Version           Repository                                 Size
=========================================================================================
Installing:
 tree        x86_64     1.6.0-10.el7      /tree-1.6.0-10.el7.x86_64                  87 k

Transaction Summary
=========================================================================================
Install  1 Package

Total size: 87 k
Installed size: 87 k
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : tree-1.6.0-10.el7.x86_64                                               1/1
  Verifying  : tree-1.6.0-10.el7.x86_64                                               1/1

Installed:
  tree.x86_64 0:1.6.0-10.el7

Complete!

12.2.4. 从本地安装

下载RPM包
wget https://mirrors.163.com/centos/7/os/x86_64/Packages/tree-1.6.0-10.el7.x86_64.rpm -O ~/tree-1.6.0-10.el7.x86_64.rpm
屏幕内容
--2021-05-11 16:09:58--  https://mirrors.163.com/centos/7/os/x86_64/Packages/tree-1.6.0-10.el7.x86_64.rpm
Resolving mirrors.163.com (mirrors.163.com)... 101.6.8.193, 2402:f000:1:408:8100::1
Connecting to mirrors.163.com (mirrors.163.com)|101.6.8.193|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 47508 (46K) [application/x-redhat-package-manager]
Saving to: ‘/root/tree-1.6.0-10.el7.x86_64.rpm’

100%[===================================================================>] 47,508      --.-K/s   in 0.03s

2021-05-11 16:09:59 (1.67 MB/s) - ‘/root/tree-1.6.0-10.el7.x86_64.rpm’ saved [47508/47508]
从文件安装
yum install -y ~/tree-1.6.0-10.el7.x86_64.rpm
屏幕内容
Loaded plugins: fastestmirror
Examining /root/tree-1.6.0-10.el7.x86_64.rpm: tree-1.6.0-10.el7.x86_64
Marking /root/tree-1.6.0-10.el7.x86_64.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package tree.x86_64 0:1.6.0-10.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=========================================================================================
 Package     Arch       Version           Repository                                 Size
=========================================================================================
Installing:
 tree        x86_64     1.6.0-10.el7      /tree-1.6.0-10.el7.x86_64                  87 k

Transaction Summary
=========================================================================================
Install  1 Package

Total size: 87 k
Installed size: 87 k
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : tree-1.6.0-10.el7.x86_64                                               1/1
  Verifying  : tree-1.6.0-10.el7.x86_64                                               1/1

Installed:
  tree.x86_64 0:1.6.0-10.el7

Complete!
使用 yum 会自动检测软件包依赖关系,从网络下载,自动安装依赖。

12.3. 重新安装

重新安装的命令: yum reinstall -y 软件包名称

具体使用方法与 安装 相同。

12.4. 查询

12.4.1. 基础用法

yum list [软件包名称或星号表达式]

yum list installed [软件包名称或星号表达式]

yum list available [软件包名称或星号表达式]

yum info 软件包名称

12.4.2. 列出所有软件包

yum list
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Installed Packages
GeoIP.x86_64                              1.5.0-13.el7                 @anaconda
NetworkManager.x86_64                     1:1.12.0-10.el7_6            @updates
......(省略部分内容)......
Available Packages
0ad.x86_64                                0.0.22-1.el7                 epel
0ad-data.noarch                           0.0.22-1.el7                 epel
0install.x86_64                           2.11-1.el7                   epel
......(省略部分内容)......

12.4.3. 列出已经安装的软件包

yum list installed
屏幕内容
Loaded plugins: fastestmirror
Installed Packages
GeoIP.x86_64                          1.5.0-13.el7               @anaconda
NetworkManager.x86_64                 1:1.12.0-10.el7_6          @updates
NetworkManager-libnm.x86_64           1:1.12.0-10.el7_6          @updates
NetworkManager-team.x86_64            1:1.12.0-10.el7_6          @updates
NetworkManager-tui.x86_64             1:1.12.0-10.el7_6          @updates
......(省略部分内容)......

12.4.4. 列出仓库中可用的软件包

yum list available
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Available Packages
0ad.x86_64                                0.0.22-1.el7                   epel
0ad-data.noarch                           0.0.22-1.el7                   epel
0install.x86_64                           2.11-1.el7                     epel
2048-cli.x86_64                           0.9.1-1.el7                    epel
2048-cli-nocurses.x86_64                  0.9.1-1.el7                    epel
......(省略部分内容)......

12.4.5. 仅显示指定名称的软件包

yum list 命令可以在尾部添加软件包名称(支持星号模糊匹配),命令输出结果中只会显示名称相关的软件包。

星号占位符表示任意字符会出现一次以上(含一次)。

显示软件包名称中包含 "openssh" 字样的结果:

yum list *openssh*
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Installed Packages
openssh.x86_64                          7.4p1-16.el7                           @anaconda
openssh-clients.x86_64                  7.4p1-16.el7                           @anaconda
openssh-server.x86_64                   7.4p1-16.el7                           @anaconda
Available Packages
gsi-openssh.x86_64                      7.4p1-6.el7                            epel
gsi-openssh-clients.x86_64              7.4p1-6.el7                            epel
gsi-openssh-server.x86_64               7.4p1-6.el7                            epel
lxqt-openssh-askpass.x86_64             0.14.1-3.el7                           epel
lxqt-openssh-askpass-l10n.noarch        0.11.2-3.el7                           epel
lxqt-openssh-askpass-l10n.x86_64        0.14.1-3.el7                           epel
openssh.x86_64                          7.4p1-21.el7                           base
openssh-askpass.x86_64                  7.4p1-21.el7                           base
openssh-cavs.x86_64                     7.4p1-21.el7                           base
openssh-clients.x86_64                  7.4p1-21.el7                           base
openssh-keycat.x86_64                   7.4p1-21.el7                           base
openssh-ldap.x86_64                     7.4p1-21.el7                           base
openssh-ldap-authkeys.noarch            0.1.0~git20200205.aee4c46-2.el7        epel
openssh-server.x86_64                   7.4p1-21.el7                           base
openssh-server-sysvinit.x86_64          7.4p1-21.el7                           base
perl-Net-OpenSSH.noarch                 0.62-1.el7                             epel

可以试一试 yum list installed opensshyum list available openssh,观察输出结果有什么不同?

去掉命令中的第一个或第二个星号,输出结果会明显不同。

12.4.6. 查看软件包信息

yum info tree
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Installed Packages
Name        : tree
Arch        : x86_64
Version     : 1.6.0
Release     : 10.el7
Size        : 87 k
Repo        : installed
Summary     : File system tree viewer
URL         : http://mama.indstate.edu/users/ice/tree/
License     : GPLv2+
Description : The tree utility recursively displays the contents of directories in a
            : tree-like format.  Tree is basically a UNIX port of the DOS tree
            : utility.

12.5. 查询(rpm)

yum 命令外,还可以使用更基础的 rpm 命令查询软件包信息。

rpm 仅对已经安装的软件包有效。

12.5.1. 列出已经安装的包

rpm -qa
屏幕内容
authconfig-6.2.8-30.el7.x86_64
kbd-legacy-1.15.5-15.el7.noarch
usermode-1.111-5.el7.x86_64
ncurses-base-5.9-14.20130511.el7_4.noarch
trousers-0.3.14-2.el7.x86_64
chrony-3.2-2.el7.x86_64
......
......
......

12.5.2. 查询文件属于哪个包

rpm -qf /usr/sbin/sshd
屏幕内容
openssh-server-7.4p1-16.el7.x86_64

12.5.3. 列出包中的文件

rpm -ql openssh-server

rpm -ql openssh-server-7.4p1-16.el7.x86_64
屏幕内容
/etc/pam.d/sshd
/etc/ssh/sshd_config
/etc/sysconfig/sshd
/usr/lib/systemd/system/sshd-keygen.service
/usr/lib/systemd/system/sshd.service
/usr/lib/systemd/system/sshd.socket
/usr/lib/systemd/system/sshd@.service
/usr/lib64/fipscheck/sshd.hmac
/usr/libexec/openssh/sftp-server
/usr/sbin/sshd
/usr/sbin/sshd-keygen
/usr/share/man/man5/moduli.5.gz
/usr/share/man/man5/sshd_config.5.gz
/usr/share/man/man8/sftp-server.8.gz
/usr/share/man/man8/sshd.8.gz
/var/empty/sshd

12.5.4. 列出包中的配置文件

rpm -qc openssh-server

rpm -qc openssh-server-7.4p1-16.el7.x86_64
屏幕内容
/etc/pam.d/sshd
/etc/ssh/sshd_config
/etc/sysconfig/sshd

12.5.5. 列出包中文件的状态

rpm -qs openssh-server
屏幕内容
normal        /etc/pam.d/sshd
normal        /etc/ssh/sshd_config
normal        /etc/sysconfig/sshd
normal        /usr/lib/systemd/system/sshd-keygen.service
normal        /usr/lib/systemd/system/sshd.service
normal        /usr/lib/systemd/system/sshd.socket
normal        /usr/lib/systemd/system/sshd@.service
normal        /usr/lib64/fipscheck/sshd.hmac
normal        /usr/libexec/openssh/sftp-server
normal        /usr/sbin/sshd
normal        /usr/sbin/sshd-keygen
normal        /usr/share/man/man5/moduli.5.gz
normal        /usr/share/man/man5/sshd_config.5.gz
normal        /usr/share/man/man8/sftp-server.8.gz
normal        /usr/share/man/man8/sshd.8.gz
normal        /var/empty/sshd

12.6. 升级

12.6.1. 基础用法

yum update -y [软件包名称或星号表达式]
常用参数
y

表示 yum 全自动执行(不交互回答问题)

12.6.2. 升级所有软件包

从网络仓库获取最新的软件包信息,下载并更新系统:

yum update -y
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package GeoIP.x86_64 0:1.5.0-13.el7 will be updated
---> Package GeoIP.x86_64 0:1.5.0-14.el7 will be an update
--> Processing Dependency: geoipupdate for package: GeoIP-1.5.0-14.el7.x86_64
---> Package NetworkManager.x86_64 1:1.12.0-10.el7_6 will be updated
---> Package NetworkManager.x86_64 1:1.18.8-2.el7_9 will be an update
......(省略部分内容)......
--> Running transaction check
---> Package bind-export-libs.x86_64 32:9.11.4-26.P2.el7_9.5 will be installed
---> Package geoipupdate.x86_64 0:2.5.0-1.el7 will be installed
--> Finished Dependency Resolution
--> Running transaction check
---> Package kernel.x86_64 0:3.10.0-957.el7 will be erased
--> Finished Dependency Resolution

Dependencies Resolved

=============================================================================
 Package          Arch    Version              Repository                Size
=============================================================================
Installing:
 iwl7260-firmware noarch  25.30.13.0-80.el7_9  updates                  6.1 M
     replacing  iwl7265-firmware.noarch 22.0.7.0-69.el7
 kernel           x86_64  3.10.0-1160.25.1.el7 updates                   50 M
 kernel-devel     x86_64  3.10.0-1160.25.1.el7 updates                   18 M
Updating:
 GeoIP           x86_64   1.5.0-14.el7         base                     1.5 M
 NetworkManager   x86_64  1:1.18.8-2.el7_9     updates                  1.9 M
......(省略部分内容)......
=============================================================================
Install    3 Packages (+2 Dependent packages)
Upgrade  265 Packages
Remove     1 Package

Total download size: 407 M
......(省略部分内容)......
Complete!

12.6.3. 升级一个或多个软件包

yum update -y vim openssh*
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package openssh.x86_64 0:7.4p1-16.el7 will be updated
......(省略部分内容)......
---> Package vim-common.x86_64 2:7.4.160-6.el7_6 will be updated
---> Package vim-common.x86_64 2:7.4.629-8.el7_9 will be an update
--> Finished Dependency Resolution

Dependencies Resolved

==================================================================
 Package            Arch      Version              Repository Size
==================================================================
Updating:
 openssh            x86_64    7.4p1-21.el7         base       510 k
 openssh-clients    x86_64    7.4p1-21.el7         base       655 k
 openssh-server     x86_64    7.4p1-21.el7         base       459 k
 vim-enhanced       x86_64    2:7.4.629-8.el7_9    updates    1.1 M
Updating for dependencies:
 vim-common         x86_64    2:7.4.629-8.el7_9    updates    5.9 M

Transaction Summary
==================================================================
Upgrade  4 Packages (+1 Dependent package)

Total size: 8.6 M
Total download size: 1.6 M
......(省略部分内容)......
Complete!

12.7. 移除

12.7.1. 基础用法

yum erase 软件包名称
为防止误操作,不建议使用 -y 参数或者星号表达式。

12.7.2. 从系统移除软件包

yum erase tree
屏幕内容
Loaded plugins: fastestmirror
Resolving Dependencies
--> Running transaction check
---> Package tree.x86_64 0:1.6.0-10.el7 will be erased
--> Finished Dependency Resolution

Dependencies Resolved

==============================================================================
 Package       Arch            Version               Repository          Size
==============================================================================
Removing:
 tree          x86_64          1.6.0-10.el7          installed           87 k

Transaction Summary
==============================================================================
Remove  1 Package

Installed size: 87 k
Is this ok [y/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Erasing    : tree-1.6.0-10.el7.x86_64                                   1/1
  Verifying  : tree-1.6.0-10.el7.x86_64                                   1/1

Removed:
  tree.x86_64 0:1.6.0-10.el7

Complete!

12.8. 下载

12.8.1. 基础用法

yum install --downloadonly --downloaddir=下载目录 [软件包名称或星号表达式]

yumdownloader [软件包名称或星号表达式]

yumdownloader --resolve [软件包名称或星号表达式]

yumdownloader --urls --resolve [软件包名称或星号表达式]
常用参数
downloadonly

不安装,仅下载软件包文件及其依赖的软件包

downloaddir

软件包文件的下载目录

urls

仅打印软件包的下载地址,不下载

resolve

检查软件包依赖关系并下载

12.8.2. 下载软件包文件方法一:yum

下载软件包文件,保存在 /tmp 目录下:

yum install --downloadonly --downloaddir=/tmp vim
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package vim-enhanced.x86_64 2:7.4.160-6.el7_6 will be updated
---> Package vim-enhanced.x86_64 2:7.4.629-8.el7_9 will be an update
--> Processing Dependency: vim-common = 2:7.4.629-8.el7_9 for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Running transaction check
---> Package vim-common.x86_64 2:7.4.160-6.el7_6 will be updated
---> Package vim-common.x86_64 2:7.4.629-8.el7_9 will be an update
--> Finished Dependency Resolution

Dependencies Resolved

============================================================================================================
 Package         Arch      Version              Repository                                              Size
============================================================================================================
Updating:
 vim-enhanced    x86_64    2:7.4.629-8.el7_9    updates                                               1.1 M
Updating for dependencies:
 vim-common      x86_64    2:7.4.629-8.el7_9    updates                                               5.9 M

Transaction Summary
============================================================================================================
Upgrade  1 Package (+1 Dependent package)

Total size: 7.0 M
Background downloading packages, then exiting:
exiting because "Download Only" specified

查看下载的软件包文件:

[root@cdgeekcamp ~]# ll /tmp/vim*
-rw-r--r-- 1 root root 6205700 Dec 18 04:37 /tmp/vim-common-7.4.629-8.el7_9.x86_64.rpm
-rw-r--r-- 1 root root 1106008 Dec 18 04:37 /tmp/vim-enhanced-7.4.629-8.el7_9.x86_64.rpm

12.8.3. 下载软件包文件方法二:yumdownloader

安装 yumdownloader 工具:

yum install -y yum-utils

查看包及其依赖关系的下载地址:

yumdownloader --urls --resolve vim
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
--> Running transaction check
---> Package vim-enhanced.x86_64 2:7.4.629-8.el7_9 will be installed
--> Processing Dependency: vim-common = 2:7.4.629-8.el7_9 for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Running transaction check
---> Package vim-common.x86_64 2:7.4.160-6.el7_6 will be updated
--> Processing Dependency: vim-common = 2:7.4.160-6.el7_6 for package: 2:vim-enhanced-7.4.160-6.el7_6.x86_64
---> Package vim-common.x86_64 2:7.4.629-8.el7_9 will be an update
--> Running transaction check
---> Package vim-enhanced.x86_64 2:7.4.160-6.el7_6 will be updated
--> Finished Dependency Resolution
http://mirrors.cloud.aliyuncs.com/centos/7/updates/x86_64/Packages/vim-enhanced-7.4.629-8.el7_9.x86_64.rpm
http://mirrors.cloud.aliyuncs.com/centos/7/updates/x86_64/Packages/vim-common-7.4.629-8.el7_9.x86_64.rpm

下载软件包及其依赖的软件包到当前目录:

yumdownloader --resolve vim
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
--> Running transaction check
---> Package vim-enhanced.x86_64 2:7.4.629-8.el7_9 will be installed
--> Processing Dependency: vim-common = 2:7.4.629-8.el7_9 for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Running transaction check
---> Package vim-common.x86_64 2:7.4.160-6.el7_6 will be updated
--> Processing Dependency: vim-common = 2:7.4.160-6.el7_6 for package: 2:vim-enhanced-7.4.160-6.el7_6.x86_64
---> Package vim-common.x86_64 2:7.4.629-8.el7_9 will be an update
--> Running transaction check
---> Package vim-enhanced.x86_64 2:7.4.160-6.el7_6 will be updated
--> Finished Dependency Resolution
Delta RPMs disabled because /usr/bin/applydeltarpm not installed.

查看下载的软件包文件:

[root@cdgeekcamp ~]# ll vim*
-rw-r--r-- 1 root root 6205700 Dec 18 04:37 vim-common-7.4.629-8.el7_9.x86_64.rpm
-rw-r--r-- 1 root root 1106008 Dec 18 04:37 vim-enhanced-7.4.629-8.el7_9.x86_64.rpm

12.9. 仓库管理

12.9.1. 基础用法

yum repolist

yum-config-manager --add-repo 文件路径或网址

yum-config-manager --enable Yum仓库名称

yum-config-manager --disable Yum仓库名称
常用参数
add-repo

从指定文件或网址增加Yum仓库(并启用)

enable

启用Yum仓库

disable

禁用Yum仓库

12.9.2. 安装依赖软件

安装 yum-config-manager 工具:

yum install -y yum-utils

12.9.3. 列出Yum仓库

yum repolist
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
repo id              repo name                                          status
base/7/x86_64        CentOS-7                                           10,072
epel/x86_64          Extra Packages for Enterprise Linux 7 - x86_64     13,592
extras/7/x86_64      CentOS-7                                              476
updates/7/x86_64     CentOS-7                                            2,189
repolist: 26,329

12.9.4. 增加并启用Yum仓库

创建临时文件 "~/nginx.repo"

cat << EOF > ~/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF

增加并启用Yum仓库:

yum-config-manager --add-repo ~/nginx.repo
屏幕内容
Loaded plugins: fastestmirror
adding repo from: /root/nginx.repo
grabbing file /root/nginx.repo to /etc/yum.repos.d/nginx.repo
repo saved to /etc/yum.repos.d/nginx.repo

确认nginx仓库已经启用:

yum repolist
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
repo id                repo name                                        status
base/7/x86_64          CentOS-7                                         10,072
epel/x86_64            Extra Packages for Enterprise Linux 7 - x86_64   13,592
extras/7/x86_64        CentOS-7                                            476
nginx-stable/7/x86_64  nginx stable repo                                   224
updates/7/x86_64       CentOS-7                                          2,189
repolist: 26,553

出现 "nginx-stable",表示nginx仓库已经启用。

12.9.5. 禁用Yum仓库

yum-config-manager --disable nginx-stable
屏幕内容
Loaded plugins: fastestmirror
============================= repo: nginx-stable =============================
[nginx-stable]
......(省略部分内容)......
enabled = 0
......(省略部分内容)......
yum repolist 命令可以帮助确认仓库状态。禁用nginx仓库后,命令结果不会有 nginx-stable 字样。

12.9.6. 启用Yum仓库

yum-config-manager --enable nginx-stable
屏幕内容
Loaded plugins: fastestmirror
============================= repo: nginx-stable =============================
[nginx-stable]
......(省略部分内容)......
enabled = 1
......(省略部分内容)......

12.10. 搜索

"search" 选项可以搜索软件包的名称、描述或简介中的文字。

12.10.1. 基础用法

yum search 关键字

12.10.2. 搜索nginx相关的软件包

yum search curl
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
======================================== N/S matched: nginx =======================================
collectd-curl.x86_64 : Curl plugin for collectd
collectd-curl_json.x86_64 : Curl JSON plugin for collectd
collectd-curl_xml.x86_64 : Curl XML plugin for collectd
curlftpfs.x86_64 : CurlFtpFS is a filesystem for accessing FTP hosts based on FUSE and libcurl
flickcurl-devel.x86_64 : Development files for flickcurl
libcurl-devel.x86_64 : Files needed for building applications with libcurl
libcurl-devel.i686 : Files needed for building applications with libcurl
nbdkit-plugin-curl.x86_64 : HTTP/FTP/SSH (cURL) plugin for nbdkit
ocaml-curl.x86_64 : OCaml Curl library (ocurl)
ocaml-curl-devel.x86_64 : Development files for ocaml-curl
perl-WWW-Curl.x86_64 : Perl extension interface for libcurl
php-pear-Net-Curl.noarch : OO interface to PHP's cURL extension
python-pycurl.x86_64 : A Python interface to libcurl
python34-pycurl.x86_64 : Python interface to libcurl for Python 3
python36-pycurl.x86_64 : Python interface to libcurl for Python 3
uwsgi-alarm-curl.x86_64 : uWSGI - Curl alarm plugin
uwsgi-plugin-curl-cron.x86_64 : uWSGI - Plugin for CURL Cron support
curl.x86_64 : A utility for getting files from remote servers (FTP, HTTP, and others)
flickcurl.x86_64 : C library for the Flickr API
libcurl.x86_64 : A library for getting files from web servers
libcurl.i686 : A library for getting files from web servers
python2-httpie.noarch : A Curl-like tool for humans
rubygem-curb.x86_64 : Ruby libcurl bindings
uget.x86_64 : Download manager using GTK+ and libcurl
uwsgi-alarm-xmpp.x86_64 : uWSGI - Curl alarm plugin

  Name and summary matches only, use "search all" for everything.
"search all" 使用频率极低。

curllibcurl-devel 是我要找的软件包名称,安装之:

yum install -y curl libcurl-devel

你找到想要的软件包了吗?

12.11. 文件属于哪个软件包

知道某个文件的名称,但不清楚具体的软件包名称时,"provides" 选项很管用。

找到软件包名称后,直接 "yum install -y 软件包名称" 搞定!

12.11.1. 基础用法

yum provides 文件绝对路径或星号表达式

12.11.2. 不知道 "curl.h" 的绝对路径时

yum provides */curl.h
"*/curl.h" 开头的星号不能少。
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
libcurl-devel-7.29.0-59.el7.i686 : Files needed for building applications with libcurl
Repo        : base
Matched from:
Filename    : /usr/include/curl/curl.h


libcurl-devel-7.29.0-59.el7.x86_64 : Files needed for building applications with libcurl
Repo        : base
Matched from:
Filename    : /usr/include/curl/curl.h
......

从结果看,只有软件包 "libcurl-devel" 包含 "*/curl.h",文件绝对路径:"/usr/include/curl/curl.h"

要不要试试 yum provides /curl.

12.11.3. 知道 "curl.h" 的绝对路径时

yum provides /usr/include/curl/curl.h
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
libcurl-devel-7.29.0-59.el7.i686 : Files needed for building applications with libcurl
Repo        : base
Matched from:
Filename    : /usr/include/curl/curl.h


libcurl-devel-7.29.0-59.el7.x86_64 : Files needed for building applications with libcurl
Repo        : base
Matched from:
Filename    : /usr/include/curl/curl.h
......

12.12. 加速网络访问

12.12.1. 用国内镜像服务器加速

备份配置文件:

cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak

使用阿里云镜像服务器:

new_mirror_url=http://mirrors.aliyun.com/

cat << EOF > /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-\$releasever
enabled=1
failovermethod=priority
baseurl=${new_mirror_url}centos/\$releasever/os/\$basearch/
gpgcheck=1
gpgkey=${new_mirror_url}centos/RPM-GPG-KEY-CentOS-7

[updates]
name=CentOS-\$releasever
enabled=1
failovermethod=priority
baseurl=${new_mirror_url}centos/\$releasever/updates/\$basearch/
gpgcheck=1
gpgkey=${new_mirror_url}centos/RPM-GPG-KEY-CentOS-7

[extras]
name=CentOS-\$releasever
enabled=1
failovermethod=priority
baseurl=${new_mirror_url}centos/\$releasever/extras/\$basearch/
gpgcheck=1
gpgkey=${new_mirror_url}centos/RPM-GPG-KEY-CentOS-7
EOF

还可以用网易的镜像服务器:

new_mirror_url=http://mirrors.163.com/

cat << EOF > /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-\$releasever
enabled=1
failovermethod=priority
baseurl=${new_mirror_url}centos/\$releasever/os/\$basearch/
gpgcheck=1
gpgkey=${new_mirror_url}centos/RPM-GPG-KEY-CentOS-7

[updates]
name=CentOS-\$releasever
enabled=1
failovermethod=priority
baseurl=${new_mirror_url}centos/\$releasever/updates/\$basearch/
gpgcheck=1
gpgkey=${new_mirror_url}centos/RPM-GPG-KEY-CentOS-7

[extras]
name=CentOS-\$releasever
enabled=1
failovermethod=priority
baseurl=${new_mirror_url}centos/\$releasever/extras/\$basearch/
gpgcheck=1
gpgkey=${new_mirror_url}centos/RPM-GPG-KEY-CentOS-7
EOF

12.12.2. 缓存仓库软件数据

yum的所有操作都会访问网络仓库服务器,makecache 后会减少多数网络请求,加速操作。

yum clean all
yum makecache
屏幕内容
Loaded plugins: fastestmirror
Determining fastest mirrors
base                                                   | 3.6 kB     00:00
epel                                                   | 4.7 kB     00:00
extras                                                 | 2.9 kB     00:00
updates                                                | 2.9 kB     00:00
(1/17): base/7/x86_64/group_gz                           | 153 kB   00:00
(2/17): base/7/x86_64/primary_db                         | 6.1 MB   00:00
(3/17): base/7/x86_64/other_db                           | 2.6 MB   00:00
(4/17): base/7/x86_64/filelists_db                       | 7.2 MB   00:00
(5/17): epel/x86_64/group_gz                             |  96 kB   00:00
(6/17): epel/x86_64/updateinfo                           | 1.0 MB   00:00
(7/17): epel/x86_64/prestodelta                          |  692 B   00:00
(8/17): epel/x86_64/filelists_db                         |  12 MB   00:00
(9/17): epel/x86_64/primary_db                           | 6.9 MB   00:00
(10/17): epel/x86_64/other_db                            | 3.4 MB   00:00
(11/17): extras/7/x86_64/primary_db                      | 236 kB   00:00
(12/17): extras/7/x86_64/filelists_db                    | 231 kB   00:00
(13/17): extras/7/x86_64/other_db                        | 139 kB   00:00
(14/17): nginx-stable/7/x86_64/primary_db                |  63 kB   00:00
(15/17): updates/7/x86_64/filelists_db                   | 4.7 MB   00:00
(16/17): updates/7/x86_64/primary_db                     | 8.0 MB   00:00
(17/17): updates/7/x86_64/other_db                       | 610 kB   00:00
Metadata Cache Created

12.13. EPEL扩展仓库

EPEL是官方维护的扩展仓库,包含很多实用的软件包。

12.13.1. 安装EPEL

yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

12.13.2. 用国内EPEL镜像服务器加速

由于官方服务器在国内速度慢,建议使用国内EPEL镜像服务器。此处以阿里云为例:

new_mirror_url=https://mirrors.aliyun.com/

cp /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.bak

sed -i "s|#baseurl=http://download.fedoraproject.org/pub/|baseurl=${new_mirror_url}|g" /etc/yum.repos.d/epel.repo

还可以替换成清华大学的服务器: "https://mirrors.tuna.tsinghua.edu.cn/"

12.13.3. 缓存仓库软件数据

设置完毕后,更新仓库缓存:

yum clean all
yum makecache

13. 服务管理

13.1. 简介

CentOS 7依靠Systemd管理各种系统服务,service start 服务名称 这种方式已经被过时,systemctl start 服务名称 才是首选。

Systemd是Linux的系统和服务管理器。提供许多特性,例如开机时并行启动服务(完美发挥SSD硬盘性能优势,不再等待排队启动服务)、按需启动服务、服务启动顺序(依赖关系)控制等。

13.1.1. 服务管理的基本逻辑

安装某个软件及其附带的服务后,设置为开机启动,大概要经过以下几个步骤:

  1. 安装(复制)服务文件("UNIT FILE")到 systemd 指定目录;

  2. 设置服务状态("STATE")为 "enabled",每次开机后服务会自动启动;

  3. 在当前系统状态下(无需重启),启动服务;

13.1.2. 一些准备工作

我们以Nginx为例,演示服务管理操作。

安装Nginx:

yum install -y nginx
屏幕内容
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
base                                                                   | 3.6 kB  00:00:00
epel                                                                   | 4.7 kB  00:00:00
extras                                                                 | 2.9 kB  00:00:00
nginx-stable                                                           | 2.9 kB  00:00:00
updates                                                                | 2.9 kB  00:00:00
(1/2): epel/x86_64/updateinfo                                          | 1.0 MB  00:00:00
(2/2): epel/x86_64/primary_db                                          | 6.9 MB  00:00:00
Resolving Dependencies
--> Running transaction check
---> Package nginx.x86_64 1:1.16.0-1.el7.ngx will be updated
---> Package nginx.x86_64 1:1.20.0-1.el7.ngx will be an update
--> Finished Dependency Resolution

Dependencies Resolved

==============================================================================================
 Package         Arch             Version                        Repository              Size
==============================================================================================
Updating:
 nginx           x86_64           1:1.20.0-1.el7.ngx             nginx-stable           790 k

Transaction Summary
==============================================================================================
Upgrade  1 Package

Total size: 790 k
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Updating   : 1:nginx-1.20.0-1.el7.ngx.x86_64                                            1/2
warning: /etc/nginx/conf.d/default.conf created as /etc/nginx/conf.d/default.conf.rpmnew
warning: /etc/nginx/nginx.conf created as /etc/nginx/nginx.conf.rpmnew
  Cleanup    : 1:nginx-1.16.0-1.el7.ngx.x86_64                                            2/2
  Verifying  : 1:nginx-1.20.0-1.el7.ngx.x86_64                                            1/2
  Verifying  : 1:nginx-1.16.0-1.el7.ngx.x86_64                                            2/2

Updated:
  nginx.x86_64 1:1.20.0-1.el7.ngx

Complete!

13.2. 列表服务

13.2.1. 基础用法

systemctl list-unit-files

systemctl list-unit --all

systemctl --failed
列表时,内容超出屏幕,显示不完。按 EnterPgDn 向下翻,按 Ctrl+Cq 退出。

13.2.2. 列出已安装的服务文件及其状态

systemctl list-unit-files
屏幕内容
UNIT FILE                                     STATE
proc-sys-fs-binfmt_misc.automount             static
dev-hugepages.mount                           static
dev-mqueue.mount                              static
sys-kernel-debug.mount                        static
tmp.mount                                     disabled
brandbot.path                                 disabled
systemd-ask-password-console.path             static
systemd-ask-password-plymouth.path            static
systemd-ask-password-wall.path                static
session-482.scope                             static
aliyun.service                                disabled
arp-ethers.service                            disabled
atd.service                                   enabled
auditd.service                                enabled
autovt@.service                               enabled
.....
systemd-readahead-done.timer                  indirect
systemd-tmpfiles-clean.timer                  static

254 unit files listed.

13.2.3. 列出已加载的服务

systemctl list-units
屏幕内容
-.mount                           loaded active mounted   /
dev-hugepages.mount               loaded active mounted   Huge Pages File System
dev-mqueue.mount                  loaded active mounted   POSIX Message Queue File System
run-user-0.mount                  loaded active mounted   /run/user/0
sys-kernel-config.mount           loaded active mounted   Configuration File System
sys-kernel-debug.mount            loaded active mounted   Debug File System
systemd-ask-password-plymouth.path loaded active waiting   Forward Password Requests to Plym
systemd-ask-password-wall.path    loaded active waiting   Forward Password Requests to Wall
session-482.scope                 loaded active running   Session 482 of user root
aegis.service                     loaded active exited    LSB: aegis update.
atd.service                       loaded active running   Job spooling tools
auditd.service                    loaded active running   Security Auditing Service
chronyd.service                   loaded active running   NTP client/server
mysqld.service                    loaded active running   MySQL Server
network.service                   loaded active running   LSB: Bring up/down networking
nginx.service                     loaded active running   nginx - high performance web serve
.....
LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

95 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

13.2.4. 列出所有服务

systemctl list-units --all
屏幕内容
  UNIT                             LOAD      ACTIVE   SUB       DESCRIPTION
  dev-ttyS0.device                 loaded    active   plugged   /dev/ttyS0
  dev-ttyS1.device                 loaded    active   plugged   /dev/ttyS1
  dev-ttyS2.device                 loaded    active   plugged   /dev/ttyS2
  dev-ttyS3.device                 loaded    active   plugged   /dev/ttyS3
  dev-vda.device                   loaded    active   plugged   /dev/vda
  dev-vda1.device                  loaded    active   plugged   /dev/vda1
......
  time-sync.target                 loaded    inactive dead      System Time Synchronized
  timers.target                    loaded    active   active    Timers
  umount.target                    loaded    inactive dead      Unmount All Filesystems
  letsencrypt.timer                loaded    active   waiting   Monthly renewal of Let's Encry
  systemd-readahead-done.timer     loaded    inactive dead      Stop Read-Ahead Data Collectio
  systemd-tmpfiles-clean.timer     loaded    active   waiting   Daily Cleanup of Temporary Dir

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

181 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.

13.2.5. 列出失败状态的服务

systemctl --failed
屏幕内容
  UNIT                     LOAD   ACTIVE SUB    DESCRIPTION
● cloud-init-local.service loaded failed failed Initial cloud-init job (pre-networking)
● cloud-init.service       loaded failed failed Initial cloud-init job (metadata service crawl
● letsencrypt.service      loaded failed failed Let's Encrypt renewal
● postfix.service          loaded failed failed Postfix Mail Transport Agent

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

4 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

13.3. 查找服务

13.3.1. 基础用法

systemctl list-unit 星号匹配表达式

systemctl list-unit --all 星号匹配表达式

13.3.2. 列出指定名称的服务文件及其状态

列出名称包含 "nginx" 字样的服务:

systemctl list-unit-files *nginx*
屏幕内容
UNIT FILE           STATE
nginx-debug.service disabled
nginx.service       enabled

2 unit files listed.

13.3.3. 列出指定名称的服务

列出名称包含 "nginx" 字样的服务:

systemctl list-units -all *nginx*
屏幕内容
UNIT          LOAD   ACTIVE   SUB  DESCRIPTION
nginx.service loaded inactive dead nginx - high performance web server

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

1 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.

13.4. 启动服务

13.4.1. 基础用法

systemctl start 服务名称

13.4.2. 启动Nginx服务

systemctl start nginx

如果启动或重启服务时,屏幕上出现类似提示:

Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.

说明服务操作失败,通过查看服务状态( systemctl status nginx ) 或 系统日志( journalctl -xe )排错即可。

13.5. 状态检查

13.5.1. 基础用法

systemctl status 服务名称

13.5.2. 查看Nginx服务状态

systemctl status nginx
屏幕内容
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2021-05-20 20:01:10 CST; 3 days ago
     Docs: http://nginx.org/en/docs/
 Main PID: 7858 (nginx)
   CGroup: /system.slice/nginx.service
           ├─7858 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
           └─7859 nginx: worker process

May 20 20:01:09 cdgeekcamp systemd[1]: Starting nginx - high performance web server...
May 20 20:01:10 cdgeekcamp systemd[1]: PID file /var/run/nginx.pid not readable (yet?) a...rt.
May 20 20:01:10 cdgeekcamp systemd[1]: Started nginx - high performance web server.
Hint: Some lines were ellipsized, use -l to show in full.

启动成功后,可以看到 "Active: active (running)" 字样。

如果启动服务时出现错误,会看到这样的内容:

屏幕内容
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Sun 2021-05-23 22:27:55 CST; 7min ago
     Docs: http://nginx.org/en/docs/
  Process: 7945 ExecStop=/bin/sh -c /bin/kill -s TERM $(/bin/cat /var/run/nginx.pid) (code=exited, status=0/SUCCESS)
  Process: 7935 ExecReload=/bin/sh -c /bin/kill -s HUP $(/bin/cat /var/run/nginx.pid) (code=exited, status=0/SUCCESS)
  Process: 7949 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)
 Main PID: 7916 (code=exited, status=0/SUCCESS)

May 23 22:27:55 cdgeekcamp systemd[1]: Stopped nginx - high performance web server.
May 23 22:27:55 cdgeekcamp systemd[1]: Starting nginx - high performance web server...
May 23 22:27:55 cdgeekcamp nginx[7949]: nginx: [emerg] unexpected ";" in /etc/nginx/ngin...:78
May 23 22:27:55 cdgeekcamp systemd[1]: nginx.service: control process exited, code=exite...s=1
May 23 22:27:55 cdgeekcamp systemd[1]: Failed to start nginx - high performance web server.
May 23 22:27:55 cdgeekcamp systemd[1]: Unit nginx.service entered failed state.
May 23 22:27:55 cdgeekcamp systemd[1]: nginx.service failed.
Hint: Some lines were ellipsized, use -l to show in full.

"Active: failed (Result: exit-code) " 说明启动服务时有错误。

注意软件打印的提示:

May 23 22:27:55 cdgeekcamp nginx[7949]: nginx: [emerg] unexpected ";" in /etc/nginx/ngin...:78

通常解决软件(此处为Nginx)配置错误后,重启服务即可。

13.6. 重启服务

13.6.1. 基础用法

systemctl restart 服务名称

13.6.2. 重启Nginx服务

systemctl restart nginx

13.7. 停止服务

13.7.1. 基础用法

systemctl stop 服务名称

13.7.2. 停止Nginx服务

systemctl stop nginx

确认Nginx服务状态:

systemctl status nginx
屏幕内容
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since Sun 2021-05-23 22:45:46 CST; 33s ago
     Docs: http://nginx.org/en/docs/
  Process: 8003 ExecStop=/bin/sh -c /bin/kill -s TERM $(/bin/cat /var/run/nginx.pid) (code=exited, status=0/SUCCESS)
  Process: 7935 ExecReload=/bin/sh -c /bin/kill -s HUP $(/bin/cat /var/run/nginx.pid) (code=exited, status=0/SUCCESS)
  Process: 7993 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
 Main PID: 7994 (code=exited, status=0/SUCCESS)

May 23 22:40:44 cdgeekcamp systemd[1]: Starting nginx - high performance web server...
May 23 22:40:45 cdgeekcamp systemd[1]: PID file /var/run/nginx.pid not readable (yet?) a...rt.
May 23 22:40:45 cdgeekcamp systemd[1]: Started nginx - high performance web server.
May 23 22:45:46 cdgeekcamp systemd[1]: Stopping nginx - high performance web server...
May 23 22:45:46 cdgeekcamp systemd[1]: Stopped nginx - high performance web server.
Hint: Some lines were ellipsized, use -l to show in full.

"Active: inactive (dead) " 表示服务未启动。

13.8. 重载服务

13.8.1. 基础用法

systemctl reload 服务名称

13.8.2. 重载Nginx服务

systemctl reload nginx

13.9. 查看服务

13.9.1. 基础用法

systemctl cat 服务名称

13.9.2. 查看Nginx服务文件内容

systemctl cat nginx
屏幕内容
# /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /var/run/nginx.pid)"
ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /var/run/nginx.pid)"

[Install]
WantedBy=multi-user.target

13.10. 禁止开机启动

13.10.1. 基础用法

systemctl disable 服务名称

13.10.2. 禁止开机启动Nginx服务

systemctl disable nginx
屏幕内容
Removed symlink /etc/systemd/system/multi-user.target.wants/nginx.service.
已经禁止开机启动的服务,重复执行 disable 操作,屏幕不会显示任何提示。

确认Nginx服务状态:

systemctl is-enabled nginx
屏幕内容
disabled
systemctl mask nginx 可以直接禁止手动启动Nginx服务,反之则是 systemctl unmask nginx

13.11. 启用开机启动

13.11.1. 基础用法

systemctl disable 服务名称

13.11.2. 开机启动Nginx服务

systemctl enable nginx
屏幕内容
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
已经禁止开机启动的服务,重复执行 enable 操作,屏幕不会显示任何提示。

确认Nginx服务状态:

systemctl is-enabled nginx
屏幕内容
enabled

附录 A: 客户端工具之Linux终端

A.1. Linux终端安装

笔记本或PC上安装有任何Linux发行版(Ubuntu、Deepin Linux、Manjaro Linux、ArchLinux等),系统自带Linux终端,无需单独安装。

A.2. Linux终端连接远程主机

使用 ssh 命令登录远程主机非常简单。如远程主机地址为 192.168.2.236,在终端输入以下命令:

ssh root@192.168.2.236

其中,root 是登录用户名。如果用户名是 mk,则这样登录:

ssh mk@192.168.2.236
appendix b.s2 1

如果你是第一次使用 ssh 连接这台远程主机,你会看到像下面这样的提示消息:

appendix b.s2 2

yes,后 Enter,继续连接

appendix b.s2 3

输入 root 用户密码,然后 Enter 。还是和设置密码时类似,密码不会显示在屏幕上

appendix b.s2 4

之前输入 yes 后,远程主机的指纹会添加到你的已知远程主机列表(~/.ssh/known_hosts),如下面的消息所示:

Warning: Permanently added '192.168.2.236' (ECDSA) to the list of known hosts.

正常情况下,每台远程主机只有一个指纹。这样做是为了网络安全,防止中间人攻击。

密码校验成功,你得到了远程主机的交互式终端权限

appendix b.s2 5

看看远程主机空间使用情况

appendix b.s2 6

A.3. Linux设置无密码登录

密码不方便记忆,有时候为了安全设置长密码让问题更凸显,也有时候是因为远程主机太多。

我个人的习惯是第一次登录之后立刻设置无密码登录,业内大家更喜欢称为密钥登录。

如果你是第一次使用无密码登录,需要生成密钥对。密钥对生成后,可以重复使用,不需要每次生成。我的远程主机使用密钥对已经超过十年。

如果你有密钥对,直接上传公钥(锁)到远程主机,使用私钥(钥匙)可以登录远程主机。不用再生成密钥对。

在开始之前,需要说明一下。

密钥对包括两个文件:私钥文件(Private Key),公钥文件(Public Key)。

私钥文件

相当于门钥匙,作为登录远程主机的关键。

公钥文件

相当于门锁,只要有钥匙就可以打开。公钥文件可以发布到任何地方,不需要保密。

私钥文件不能外泄,否则远程主机有严重的安全风险。
不然,某天你可能收到勒索邮件,对方要求支付10个比特币,否则删除数据库。

A.3.1. 生成密钥对

生成不带密码的密钥对: ssh-keygen -N "" -f ~/.ssh/mk

~/.ssh/mk 只是密钥对文件名前缀,可以随意更换。比如,~/.ssh/prolinux
appendix_b.s3-1

如下图所示,会生成两个文件:

  • 私钥文件: ~/.ssh/mk

  • 公钥文件: ~/.ssh/mk.pub

appendix_b.s3-2

A.3.2. 上传公钥文件到远程主机

OK,按照上面的命令,你得到了公钥文件 ~/.ssh/mk.pub

接下来,将公钥文件上传到 192.168.2.236(安装一把远程主机的“锁”)。

然后,你才能用私钥(钥匙)登录远程主机。

步骤如下:

  1. 首先,执行命令:

ssh-copy-id -i ~/.ssh/mk.pub root@192.168.2.236
appendix_b.s3-3
  1. 输入远程主机密码

在输入密码时,屏幕上是看不见密码的
appendix_b.s3-4
  1. 密码检验成功,你会看到与以下图片类似的结果

appendix_b.s3-5

至此,就给远程主机安装上了一把“锁”。

A.3.3. 在本地Linux终端中配置私钥

我们搞定“锁”之后,在本地Linux终端中配置“钥匙”。

多远程主机使用相同私钥

你可以增加 IdentityFile ~/.ssh/mk 一行到配置文件中。这样的话,可以使用 ~/.ssh/mk 登录所有远程主机。

echo "IdentityFile ~/.ssh/mk" >> ~/.ssh/config
appendix_b.s3-6
远程主机使用指定私钥

Host 参数也支持较复杂的私钥设置。

语法如下:

Host 192.168.2.236
    IdentityFile ~/.ssh/mk

还不会在Linux下编辑文件?

你可以一句话增加设置到文件:

cat << EOF >> ~/.ssh/config
Host 192.168.2.236
    IdentityFile ~/.ssh/mk
EOF
执行这个命令时,必须按两次 Enter

Host 后面的IP地址表示登录远程主机:192.168.2.236 时,使用私钥 ~/.ssh/mk

appendix_b.s3-7

你猜得没错,Host 参数可以填写多个IP地址,以空格隔开:

Host 192.168.2.236 118.23.47.90

A.3.4. 测试无密码登录

远程主机已经装上锁,也创建了本地配置文件。现在可以测试下:

ssh root@192.168.2.236
appendix_b.s3-8

无密码登录远程主机成功。

exit 可以注销(退出登录)。我推荐按 Ctrl+D 退出,更方便。

appendix_b.s3-9
appendix_b.s3-10

A.3.5. Troubleshooting

保证以下关键点正确无误,就可以100%配置成功。

客户端:“~/.ssh/”文件夹
  • ~/.ssh/ 文件夹只能被当前用户写入,也就是下图标记的 drwxr-xr-x 中第一个 w 必须存在。

修复方法: chmod 700 ~/.ssh/

appendix_b.s3-11
客户端:“~/.ssh/mk”私钥文件
  • ~/.ssh/mk 文件权限必须是 600,也就是标记的这样 -rw-------

修复方法: chmod 600 ~/.ssh/mk

appendix_b.s3-12

文件权限错误时,私钥无法登录并报错

appendix_b.s3-13
服务端(192.168.2.236):“~/.ssh/”文件夹
  • ~/.ssh/ 文件夹只能被当前用户写入,也就是下图标记的 drwx------ 中第一个 w 必须存在。

修复方法: chmod 755 ~/.ssh/

appendix_b.s3-14
服务端(192.168.2.236):“~/.ssh/authorized_keys”文件
  • ~/.ssh/authorized_keys 文件同样只能被当前用户写入,权限可以是 400-r------- )或者 600-rw------- )。

修复方法: chmod 600 ~/.ssh/authorized_keys

使用 ssh-copy-id 上传公钥,权限必须是 600-rw------- )。

如下图所示:

appendix_b.s3-15
  • ~/.ssh/authorized_keys 中每一行都是一把“锁”(公钥),对应一把“钥匙”(私钥)。也就是说,可以多人同时使用相同用户名但不同私钥登录远程主机。

appendix_b.s3-16
查看ssh命令日志

查看日志是诊断连接问题最重要的手段。

第一种是远程主机系统的登录日志文件,另一种是执行 ssh 命令时打印出来的调试信息。

这里以后者为例:ssh root@192.168.2.236 -v

appendix_b.s3-17

可以看到截图中有以下信息:

debug1: Trying private key: /home/mk/.ssh/mk
debug1: Authentication succeeded (publickey).
appendix_b.s3-18

这意味着,我们配置的 config 文件生效了。

如果这个地方没有你配置的私钥文件,请检查 ~/.ssh/config 文件配置

附录 B: 传输文件之Linux终端

B.1. Linux终端

跟着下面的例子练习,只用三分钟搞定 scp 命令传输文件。

按照本书惯例,
本地 是指当前的操作界面,可以是 电脑手机其它远程主机。比如,我操作的 mk@archlinux 终端。
远程主机 是指服务器用途的系统,可以是物理裸机、云服务器、虚拟机。比如,第一章安装的虚拟机(192.168.2.236)。

B.1.1. 准备文件

  • 在终端中创建目录,名称为 "ProLinux"

mkdir ProLinux
  • 在目录 "ProLinux" 下创建名为 "foo.txt" 的文件,文件内容为 "test text: foo"

echo 'test text: foo' > ProLinux/foo.txt
  • 同样的方式创建 "bar.txt"

echo 'test text: bar' > ProLinux/bar.txt
  • 查看目录 "ProLinux" 下的文件,确认是否创建成功:

ls -l ProLinux/
操作演示
[mk@archlinux ~]$ ls -l ProLinux/
总用量 8
-rw-r--r-- 1 mk mk 15  2月 26 15:06 bar.txt
-rw-r--r-- 1 mk mk 15  2月 26 15:06 foo.txt

B.1.2. 本地到远程主机

从本地上传目录到远程主机
  • 上传整个 "ProLinux" 目录到远程主机 "192.168.2.236" 上,登录用户名为 "root",保存路径为root用户的家目录 "~"/root 目录):

scp -r ProLinux/ root@192.168.2.236:~
操作演示
[mk@archlinux ~]$ scp -r ProLinux/ root@192.168.2.236:~
bar.txt                                       100%   15     6.0KB/s   00:00
foo.txt                                       100%   15    26.4KB/s   00:00
从本地上传文件到远程主机
  • 上传指定文件:

scp ProLinux/bar.txt root@192.168.2.236:~/ProLinux/
操作演示
[mk@archlinux ~]$ scp ProLinux/bar.txt root@192.168.2.236:~/ProLinux/
bar.txt                                       100%   15     6.2KB/s   00:00
  • 上传多个文件:

scp ProLinux/foo.txt ProLinux/bar.txt  root@192.168.2.236:~/ProLinux/
操作演示
[mk@archlinux ~]$ scp ProLinux/foo.txt ProLinux/bar.txt root@192.168.2.236:~/ProLinux/
foo.txt                                       100%   15     5.6KB/s   00:00
bar.txt                                       100%   15    34.8KB/s   00:00
  • 可以使用星号 * 模糊匹配文件名,上传 "ProLinux" 目录下所有文件:

scp ProLinux/* root@192.168.2.236:~/ProLinux/
操作演示
[mk@archlinux ~]$ scp ProLinux/* root@192.168.2.236:~/ProLinux/
bar.txt                                       100%   15     5.3KB/s   00:00
foo.txt                                       100%   15    28.2KB/s   00:00
确认上传
  • 登录远程主机:

ssh root@192.168.2.236
  • 查看 "ProLinux" 目录:

ls -l ~
操作演示
[root@prolinux ~]# ls -l ~
total 0
drwxr-xr-x. 2 root root 36 Feb 26 15:10 ProLinux
  • 查看 "ProLinux" 目录下的文件:

ls -l ~/ProLinux
操作演示
[root@prolinux ~]# ls -l ~/ProLinux
total 8
-rw-r--r--. 1 root root 15 Feb 26 15:12 bar.txt
-rw-r--r--. 1 root root 15 Feb 26 15:12 foo.txt

B.1.3. 从远程主机下载文件到本地

方法简单,交换 scp 命令中间的两部分。

  • 从远程主机下载 "~/ProLinux" 目录:

scp -r root@192.168.2.236:~/ProLinux/ ~/
操作演示
[mk@archlinux ~]$ scp -r root@192.168.2.236:~/ProLinux/ ~/
bar.txt                                       100%   15     8.7KB/s   00:00
foo.txt                                       100%   15    38.7KB/s   00:00
  • 从远程主机下载 "foo.txt" 到本地:

scp root@192.168.2.236:~/ProLinux/foo.txt ~/ProLinux
操作演示
[mk@archlinux ~]$ scp root@192.168.2.236:~/ProLinux/foo.txt ~/ProLinux
foo.txt                                       100%   15    47.2KB/s   00:00

附录 C: egrep正则表达式扩展

C.1. 字符分类

根据习惯,可以将常见字符按范围分为:

大写字母

ABCDEFGHIJKLMNOPQRSTUVWXYZ

小写字母

abcdefghijklmnopqrstuvwxyz

数字

0123456789

空格

Space

制表符

Tab

英文标点符号

`-=~!@#$%^&*()_+[]/{}|;':",./<>?

标准的正则表达式规范中,可以用 [A-Za-z] 这样的范围表达式来表示26个大写字母和26个小写字母。

C.2. 范围表达式

grep 使用特殊的范围表达式 [[:分类名称:]] 达到同样的效果。

具体的对照表如下:

分类名称 说明 示例

[:lower:]

26小写字母,相当于 [a-z]

egrep '[[:lower:]]' ~/access.log

[:upper:]

26大写字母,相当于 [A-Z]

egrep '[[:upper:]]' ~/access.log

[:digit:]

阿拉伯数字,相当于 [0-9]

egrep '[[:digit:]]' ~/access.log

[:alpha:]

大小写字母,[:lower:][:upper:] 的简写,相当于 [A-Za-z]

egrep '[[:alpha:]]' ~/access.log

[:alnum:]

大小写字母和阿拉伯数字,[:alpha:][:digit:] 的简写,相当于 [0-9A-Za-z]

egrep '[[:alnum:]]' ~/access.log

[:space:]

空格(Space)。

egrep '[[:space:]]' ~/access.log

[:blank:]

空格(Space)和制表符号(Tab)。

egrep '[[:blank:]]' ~/access.log

[:punct:]

英文标点符号,包括:

  • `-=

  • ~!@#$%^&*()_+

  • []/

  • {}|

  • ;'

  • :"

  • ,./

  • <>?

egrep '[[:punct:]]' ~/access.log

[:cntrl:]

(不可见的)控制符,包含ASCII编码中0~31(Null char~Unit Separator)、127(Delete)。

egrep '[[:cntrl:]]' ~/access.log

[:graph:]

可见字符,[:alnum:][:punct:] 的简写。

egrep '[[:graph:]]' ~/access.log

[:print:]

可打印的字符,[:alnum:][:punct:][:space:] 的简写。

egrep '[[:print:]]' ~/access.log

[:xdigit:]

十六进制数字:

  • 0123456789

  • ABCDEF

  • abcdef

相当于 [0-9A-Fa-f]

egrep '[[:xdigit:]]' ~/access.log

当然,egrep 也支持取反操作符(^)。如:

egrep '[^[:digit:]]' ~/access.log

匹配不含数字的行,等同匹配包含大小写字母或英文标点符号的行。

屏幕内容
foo.org 80 118.118.47.239 [18/Jan/2021:01:00:23] "GET /360.html HTTP/1.1" 200
bar.org 8080 115.202.80.105 [19/Feb/2021:02:12:24] "POST /login HTTP/1.1" 404
qux.com 80 123.6.49.36 [20/Mar/2021:03:22:24] "GET / HTTP/1.1" 200
quux.com 80 180.101.214.20 [21/Apr/2021:04:15:24] "GET /main.html HTTP/1.1" 200
quz.io 8080 180.101.52.35 [21/Aug/2021:13:18:24] "GET /log.jpg HTTP/1.1" 200
quuz.cn 8080 180.101.52.35 [21/Aug/2021:13:18:24] "GET /jquery.min.js HTTP/1.1" 403
quuuz.cn 8080 125.64.14.56 [21/Aug/2021:13:18:24] "GET /load.js HTTP/1.1" 200
corge.com 80 148.72.153.60 [22/May/2021:23:25:16] "GET /7.html HTTP/1.1" 500
garply.net 80 123.178.50.195 [23/Oct/2021:23:50:16] "POST /article/ HTTP/1.1" 301
garply.net 80 123.178.50.195 [23/Oct/2021:23:50:16] "POST /article_new/ HTTP/1.1" 200

以上每行都包含了字母,所以测试结果是正确的。

set 限制解除