Linux 基础与服务


目录

第一部分:Linux 基础

章节主题关键词
1Linux 安装与服务器常用命令CentOS, 远程连接, 系统目录
2vim 文本编辑器三种模式, 高效编辑
3用户管理useradd, UID, /etc/passwd
4权限管理chmod, chown, SUID, ACL
5进程管理ps, top, kill, systemd
6软件管理yum, rpm, 源码编译
7Shell 高级命令grep, awk, sed, sort, cut
8磁盘管理fdisk, mkfs, mount, LVM
9网络管理ip, nmcli, DNS, 路由
10内核模块管理lsmod, modprobe

第二部分:Linux 基础服务

章节主题关键词
11计划任务crontab, at, systemctl
12SSH 远程管理sshd_config, 密钥认证, 安全加固
13日志服务rsyslog, logrotate
14NFS 文件服务器exports, mount
15DHCP 服务器dhcpd.conf, 地址池
16Apache Web 服务器httpd.conf, 虚拟主机, SSL
17DNS 域名解析named.conf, 正向/反向解析
18NTP 时间服务器chrony, ntpdate
19邮件服务器postfix, dovecot

第一部分:Linux 基础


第 1 章 Linux 安装与服务器常用命令

1.1 为什么服务器都用 Linux?

生活类比:Windows 像精装公寓——开箱即用,但不能随便改造;Linux 像毛坯房——需要自己装修,但每面墙都可以按你的需求来设计。

服务器需要的是 稳定、免费、可控,Linux 恰好满足这三点。全球超过 90% 的服务器运行 Linux。

1.2 CentOS 系统安装要点

学校机房常用 CentOS 7(社区企业版),它和 Red Hat Enterprise Linux(RHEL)几乎一样,但完全免费。

安装时注意以下选项:

选项推荐设置原因
语言English服务器建议用英文,避免乱码
安装类型Minimal Install最小化安装,不装图形界面
分区/boot 500MB, swap=内存×1.5, 其余给 /简单方案
网络打开以太网开关默认是关闭的!

1.3 服务器必备命令速查

以下命令是服务器日常运维的"瑞士军刀",跳过基础的文件操作(ls/cd/cp),聚焦服务器场景。

系统信息查看

# 查看操作系统版本——相当于看"身份证"
[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

# 查看内核版本
[root@server ~]# uname -r
3.10.0-1160.el7.x86_64

# 查看系统全面信息
[root@server ~]# uname -a
Linux server.example.com 3.10.0-1160.el7.x86_64 #1 SMP ... x86_64 GNU/Linux

# 查看主机名
[root@server ~]# hostname
server.example.com

# 临时修改主机名(重启失效)
[root@server ~]# hostname newname

# 永久修改主机名(CentOS 7)
[root@server ~]# hostnamectl set-hostname newname

系统资源监控

# 查看内存使用——像查看水箱还剩多少水
[root@server ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           1.8G        356M        1.2G        8.5M        278M        1.3G
Swap:          2.0G          0B        2.0G

# 查看磁盘空间——看每个"抽屉"还剩多少
[root@server ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   17G  2.1G   15G  13% /
/dev/sda1                497M  125M  373M  26% /boot

# 查看CPU信息
[root@server ~]# lscpu
Architecture:          x86_64
CPU(s):                2
Model name:            Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz

# 查看系统运行时间和负载
[root@server ~]# uptime
 14:30:15 up 3 days,  2:15,  2 users,  load average: 0.00, 0.01, 0.05

想一想load average 后面的三个数字分别代表什么时间段的平均负载?

答:分别代表 1 分钟、5 分钟、15 分钟的系统负载。数值越小说明系统越空闲。一般来说,负载值不应超过 CPU 核心数。

系统关机与重启

# 立刻重启
[root@server ~]# reboot

# 定时关机——10分钟后关机
[root@server ~]# shutdown -h +10

# 定时关机——今晚11点关机
[root@server ~]# shutdown -h 23:00

# 取消关机
[root@server ~]# shutdown -c

1.4 Linux 目录结构速记

类比:Linux 的目录就像一棵倒过来的树,/(根目录)是树根,所有文件都从它长出来。

/                   根目录(一切的起点)
├── boot/           启动文件、内核(千万别动!)
├── etc/            配置文件(所有服务的"说明书"都在这里)
├── home/           普通用户的家
├── root/           root用户的家
├── var/            经常变化的数据(日志、网站文件)
├── tmp/            临时文件(重启会清空)
├── usr/            用户安装的程序
├── opt/            第三方软件
├── mnt/            临时挂载点
└── dev/            设备文件(硬盘、光驱等)

1.5 文件内容查看技巧

# head——只看前面几行(像快速翻书的开头)
[root@server ~]# head -n 5 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

# tail——只看末尾几行(日志排错时超好用)
[root@server ~]# tail -n 20 /var/log/messages

# tail -f——实时跟踪日志(盯着日志看新消息)
[root@server ~]# tail -f /var/log/secure
# 这时如果有人SSH登录,你能实时看到记录

# cat——全部显示(文件短的时候用)
[root@server ~]# cat /etc/hostname

# less——翻页查看(文件长的时候用,按 q 退出)
[root@server ~]# less /var/log/messages
# 操作:空格翻下一页,b翻上一页,/搜索,q退出

思考题:服务器出了问题,你想看最近的报错日志,应该用 head 还是 tail?为什么?

答:用 tail,因为日志文件是追加写入的,最新的记录在文件末尾。


第 2 章 vim 文本编辑器

2.1 为什么必须学 vim?

问题:服务器上一般没有图形界面,怎么编辑配置文件?

vim 是 Linux 服务器上最常用的文本编辑器。它是 vi 的增强版,几乎所有 Linux 系统都预装了。学好 vim,就像随身带了一个高效的"记事本"。

类比:vim 像一把瑞士军刀——刚开始觉得复杂,但一旦熟练,编辑速度远超鼠标点击。

2.2 vim 的三种模式

这是理解 vim 的关键:

┌──────────────┐     按 i/a/o      ┌──────────────┐
│   命令模式    │ ──────────────> │   输入模式    │
│  (默认模式)   │ <────────────── │  (编辑内容)   │
└──────┬───────┘     按 Esc       └──────────────┘
       │ 按 :
       ▼
┌──────────────┐
│   末行模式    │
│ (保存/退出/替换) │
└──────────────┘
模式作用怎么进入
命令模式移动光标、复制、删除、粘贴打开文件默认进入;任何模式按 Esc 回到此模式
输入模式像普通编辑器一样打字在命令模式下按 i/a/o
末行模式保存、退出、查找替换在命令模式下按 :

2.3 命令模式——进入输入模式的 6 种方式

按键作用记忆方法
i在光标开始输入insert(插入)
I行首开始输入大写 I → 跳到最前面
a在光标开始输入append(追加)
A行尾开始输入大写 A → 跳到最后面
o下方新建一行并输入open new line below
O上方新建一行并输入大写 O → 在上面开

2.4 命令模式——高效编辑操作

光标移动:
  h  左移一个字符
  j  下移一行        (想象 j 像一个向下的箭头)
  k  上移一行
  l  右移一个字符
  0  跳到行首
  $  跳到行尾
  gg 跳到文件开头
  G  跳到文件末尾
  :n 跳到第 n 行     例如 :50 跳到第50行

删除:
  x  删除光标所在字符
  dd 删除(剪切)当前行
  3dd 删除3行
  dG 从当前行删除到文件末尾

复制和粘贴:
  yy 复制当前行
  3yy 复制3行
  p  粘贴到当前行的下方
  P  粘贴到当前行的上方

撤销和重做:
  u  撤销(Undo)
  Ctrl+r  重做(Redo)

2.5 末行模式——保存、退出、查找替换

保存和退出:
  :w        保存(不退出)
  :q        退出(未修改时)
  :wq       保存并退出
  :q!       强制退出(不保存修改)
  :wq!      强制保存退出(需要root权限)

查找:
  /关键词    向下搜索,n跳到下一个,N跳到上一个
  ?关键词    向上搜索

替换(非常重要!服务器配置常用):
  :s/old/new/          替换当前行第一个匹配
  :s/old/new/g         替换当前行所有匹配
  :%s/old/new/g        替换整个文件所有匹配
  :10,20s/old/new/g    替换第10到20行的所有匹配

设置:
  :set nu       显示行号
  :set nonu     取消行号

2.6 实战练习:用 vim 编辑一个配置文件

# 创建一个测试文件
[root@server ~]# vim /tmp/test.conf

# 进入后:
# 1. 按 i 进入输入模式,输入以下内容:
#    server_name = myserver
#    port = 8080
#    debug = false
#
# 2. 按 Esc 回到命令模式
# 3. 输入 :wq 保存退出
#
# 4. 再次打开:vim /tmp/test.conf
# 5. 输入 :set nu 显示行号
# 6. 输入 :%s/8080/9090/g  把端口改成9090
# 7. 输入 :wq 保存退出

思考题:你在编辑配置文件时不小心按了 Esc 又乱按了几个键,文件内容变得乱七八糟,怎么办?

答:按 u 多次撤销,或者按 :q! 强制退出不保存,然后重新打开文件。


第 3 章 用户管理

3.1 为什么需要多用户?

类比:一栋公寓楼有不同的住户。管理员(root)有万能钥匙,每个住户(普通用户)只能进自己的房间。这样即使某个住户的东西被偷了,也不会影响到其他住户。

在服务器上,多用户系统能实现:

  • 权限隔离:网站管理员只能管网站,数据库管理员只能管数据库
  • 安全审计:可以追踪谁做了什么操作
  • 资源控制:限制某个用户能使用的 CPU 和内存

3.2 UID 系统——用户的"身份证号"

Linux 不认识用户名,只认识 UID(User ID,用户标识号)。

UID 范围含义类比
0root 超级管理员物业总经理,什么都能做
1-999系统账号(如 bin, daemon)楼里的各种设备间(不需要人住)
1000-60000普通用户普通住户
# 查看用户 UID 信息
[root@server ~]# id root
uid=0(root) gid=0(root) groups=0(root)

[root@server ~]# id alice
uid=1000(alice) gid=1000(alice) groups=1000(alice)

3.3 /etc/passwd——用户信息的"户口本"

[root@server ~]# head -3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

每一行有 7 个字段,用冒号 : 分隔:

用户名 : 密码占位 : UID : GID : 描述信息 : 家目录 : 登录Shell
root    : x         : 0   : 0   : root     : /root  : /bin/bash
字段含义备注
用户名登录用的名字
x密码存在 /etc/shadow 中早期直接存密码,不安全
UID用户标识号0=root
GID用户所属主组的标识号
描述用户全名或备注可以为空
家目录用户登录后的默认目录root 是 /root
Shell用户能使用的命令解释器/sbin/nologin 表示禁止登录

想一想:为什么密码字段只显示一个 x,而不是真正的密码?

答:真正的密码(加密后的)保存在 /etc/shadow 文件中,该文件只有 root 能读取,这样更安全。

3.4 用户管理命令

添加用户

# 最简单的添加用户
[root@server ~]# useradd alice

# 验证用户是否创建成功
[root@server ~]# id alice
uid=1001(alice) gid=1001(alice) groups=1001(alice)

# 指定 UID 和附加信息
[root@server ~]# useradd -u 2000 -c "Math Teacher" -s /bin/bash bob

# 创建用户时指定附加组
[root@server ~]# useradd -G wheel charlie
# wheel 组相当于"管理员后备队",可以使用 sudo

# 设置密码(必须!否则用户无法登录)
[root@server ~]# passwd alice
Changing password for user alice.
New password:          ← 输入密码(不显示字符,正常)
Retype new password:   ← 再输入一次
passwd: all authentication tokens updated successfully.

修改用户

# 修改用户的 Shell(禁止登录)
[root@server ~]# usermod -s /sbin/nologin alice

# 修改用户的家目录
[root@server ~]# usermod -d /home/newhome alice

# 把用户加入附加组(-a 追加,千万别漏了 -a,否则会清除之前的组)
[root@server ~]# usermod -aG wheel alice

# 锁定用户账号(临时禁止登录)
[root@server ~]# usermod -L alice

# 解锁用户账号
[root@server ~]# usermod -U alice

删除用户

# 删除用户(保留家目录)
[root@server ~]# userdel alice

# 删除用户并删除家目录(推荐,干净彻底)
[root@server ~]# userdel -r alice

3.5 用户组管理

类比:用户组就像"兴趣小组"——一个用户可以属于多个组,同一个组的成员共享权限。

# 创建组
[root@server ~]# groupadd teachers

# 把用户加入组
[root@server ~]# gpasswd -a alice teachers

# 查看组成员
[root@server ~]# grep teachers /etc/group
teachers:x:1002:alice,bob

# 删除组
[root@server ~]# groupdel teachers

# 查看用户所属的所有组
[root@server ~]# groups alice
alice : alice teachers

思考题:老师让你创建一个用户 student01,UID 为 3001,加入 students 组,家目录为 /home/stu01,并且不允许该用户登录 Shell。你能写出完整的命令吗?

groupadd students
useradd -u 3001 -G students -d /home/stu01 -s /sbin/nologin student01
passwd student01

第 4 章 权限管理

4.1 文件权限——公寓的钥匙系统

类比:假设你住在一栋公寓里:

  • 所有者权限(u):你自己家的钥匙,可以随意进出、装修
  • 所属组权限(g):你的家人也有钥匙,可以进出但不能装修
  • 其他人权限(o):陌生人——只能在门口看看
[root@server ~]# ls -l /etc/passwd
-rw-r--r--. 1 root root 2301 Jan 15 10:30 /etc/passwd

解读这个权限字符串 -rw-r--r--

-  rw-  r--  r--
│  │    │    │
│  │    │    └── 其他人(o):只读(r--)
│  │    └─────── 所属组(g):只读(r--)
│  └──────────── 所有者(u):读写(rw-)
└─────────────── 文件类型:- 普通文件,d 目录,l 链接
权限符号对文件的含义对目录的含义数字值
r读取内容查看目录下的文件列表(ls)4
w修改内容在目录中创建/删除文件2
x执行程序进入该目录(cd)1
-没有该权限没有该权限0

4.2 chmod——修改权限

数字方式(推荐,快速)

# rwx = 4+2+1 = 7, rw- = 4+2+0 = 6, r-- = 4+0+0 = 4

# 设置权限为:所有者rwx, 组r-x, 其他人r-x(即755)
[root@server ~]# chmod 755 /opt/script.sh

# 设置权限为:所有者rw-, 组r--, 其他人r--(即644)
[root@server ~]# chmod 644 /etc/myconfig.conf

# 常用权限组合:
# 755 → rwxr-xr-x → 目录、脚本
# 644 → rw-r--r-- → 普通文件、配置文件
# 700 → rwx------ → 只有自己能操作
# 600 → rw------- → 敏感文件(如密钥)

# 递归修改目录及其所有子文件
[root@server ~]# chmod -R 755 /var/www/html/

字母方式(直观)

# 给所有者加执行权限
[root@server ~]# chmod u+x script.sh

# 去掉其他人的读权限
[root@server ~]# chmod o-r secret.txt

# 给所有人加写权限
[root@server ~]# chmod a+w shared.txt

4.3 chown 和 chgrp——修改所有者和所属组

# 修改文件的所有者
[root@server ~]# chown alice /home/alice/report.txt

# 修改文件的所有者和所属组(一次性搞定)
[root@server ~]# chown alice:teachers /home/alice/report.txt

# 只修改所属组
[root@server ~]# chgrp teachers /home/alice/report.txt

# 递归修改目录
[root@server ~]# chown -R www:www /var/www/html/

4.4 特殊权限

除了基本的 rwx,Linux 还有三种特殊权限,在服务器管理中非常重要。

SUID(Set UID)——"借用"文件所有者的权限

类比:ATM 机——你用 ATM 取钱时,实际上是 ATM 代替你去金库取钱。ATM 程序拥有"银行金库"的访问权限(SUID),但你只能通过 ATM 规定的操作来取钱。

# 典型例子:passwd 命令
[root@server ~]# ls -l /usr/bin/passwd
-rwsr-xr-x. 1 root root 27832 Jan 10  2019 /usr/bin/passwd
#   ^
#   s 就是 SUID 标记

# 普通用户执行 passwd 时,临时拥有 root 的权限来修改密码文件
# 但只能通过 passwd 这个程序规定的功能来操作
# 设置 SUID
[root@server ~]# chmod u+s /opt/myprogram
# 或用数字:chmod 4755 /opt/myprogram(前面加4)

# 取消 SUID
[root@server ~]# chmod u-s /opt/myprogram

SGID(Set GID)——"借用"文件所属组的权限

用在目录上:目录下新建的文件自动继承该目录的所属组。

# 创建一个共享目录,让 teachers 组的人在里面协作
[root@server ~]# mkdir /opt/shared
[root@server ~]# chgrp teachers /opt/shared
[root@server ~]# chmod 2770 /opt/shared   # 2 代表 SGID

# 验证:alice(属于teachers组)在里面创建文件
[alice@server ~]$ touch /opt/shared/notes.txt
[alice@server ~]$ ls -l /opt/shared/notes.txt
-rw-rw----. 1 alice teachers 0 Mar 15 10:00 notes.txt
# 注意:所属组自动变成 teachers,而不是 alice 的默认组

Sticky Bit(粘滞位)——"只能删自己的文件"

类比:公共储物柜——每个人都可以放东西进去,但只能取走自己的东西。

# /tmp 目录就是典型的 Sticky Bit 目录
[root@server ~]# ls -ld /tmp
drwxrwxrwt. 10 root root 4096 Mar 15 10:00 /tmp
#          ^
#          t 就是 Sticky Bit 标记

# 设置 Sticky Bit
[root@server ~]# chmod o+t /opt/public
# 或用数字:chmod 1777 /opt/public(前面加1)

4.5 ACL(访问控制列表)——精细权限管理

问题:基本权限只有"所有者/组/其他人"三类,如果我想让某一个特定用户访问某个文件,但他的组又没有权限,怎么办?

# 查看文件的 ACL
[root@server ~]# getfacl /opt/project/config.txt
# file: /opt/project/config.txt
# owner: root
# group: root
user::rw-
group::r--
other::r--

# 给 alice 单独添加读写权限(不影响其他人)
[root@server ~]# setfacl -m u:alice:rw /opt/project/config.txt

# 再查看
[root@server ~]# getfacl /opt/project/config.txt
user::rw-
user:alice:rw-      ← 新增的ACL规则
group::r--
other::r--

# 注意:设置了ACL的文件,ls -l 会显示一个 + 号
[root@server ~]# ls -l /opt/project/config.txt
-rw-rw-r--+ 1 root root 100 Mar 15 10:00 config.txt

# 删除 ACL 规则
[root@server ~]# setfacl -x u:alice /opt/project/config.txt

# 删除所有 ACL 规则
[root@server ~]# setfacl -b /opt/project/config.txt

思考题:一个目录权限设为 777,但里面某个文件权限是 600(只有所有者能读写)。请问其他人能不能通过 cd 进入这个目录?能不能读取这个文件?

答:能进入目录(因为目录有 x 权限),但不能读取文件(因为文件的权限是 600)。目录权限控制"能不能进门",文件权限控制"能不能动里面的东西"。


第 5 章 进程管理

5.1 什么是进程?

类比:程序就像一个菜谱(写在纸上的做法),而进程就是按照菜谱正在做菜的过程——它需要灶台(CPU)、食材(内存)、锅碗(硬盘和网络)。

进程是运行中的程序实例。每个进程都有一个唯一的 PID(Process ID,进程号)。

5.2 查看进程

ps——静态快照

# ps -ef:查看所有进程(最常用)
[root@server ~]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Mar12 ?        00:00:05 /usr/lib/systemd/systemd
root         2     0  0 Mar12 ?        00:00:00 [kthreadd]
root       520     1  0 Mar12 ?        00:00:10 /usr/sbin/sshd -D
root      1234   520  0 10:30 ?        00:00:00 sshd: alice [priv]

# 字段说明:
# UID   → 进程所属用户
# PID   → 进程号(杀进程要用这个)
# PPID  → 父进程号(谁启动了它)
# CMD   → 进程对应的命令

# ps aux:另一种常用格式,显示CPU和内存占用
[root@server ~]# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.3 128080  6820 ?        Ss   Mar12   0:05 /usr/lib/systemd/systemd
root       520  0.0  0.1 112760  4244 ?        Ss   Mar12   0:10 /usr/sbin/sshd

# STAT 状态说明:
# R → 运行中(Running)
# S → 睡眠中(Sleeping,等待事件)
# D → 不可中断睡眠(通常在等待I/O)
# Z → 僵尸进程(已终止但父进程未回收)
# T → 已停止(Stopped)
# s → 主进程(session leader)
# + → 前台进程

# 查找特定进程
[root@server ~]# ps aux | grep sshd
root       520  0.0  0.1 112760  4244 ?        Ss   Mar12   0:10 /usr/sbin/sshd -D
root      1234  0.0  0.2 154872  5568 ?        Ss   10:30   0:00 sshd: alice [priv]

top——动态实时监控

[root@server ~]# top
top - 14:30:00 up 3 days,  2:15,  2 users,  load average: 0.05, 0.03, 0.01
Tasks: 120 total,   1 running, 119 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.3 us,  1.0 sy,  0.0 ni, 96.5 id,  0.2 wa,  0.0 hi,  0.0 si
MiB Mem :   1838.5 total,   1200.0 free,    356.2 used,    282.3 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   1300.5 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1234 root      20   0  154872   5568   4200 S   0.3  0.3   0:00.50 sshd
  520 root      20   0  112760   4244   3500 S   0.0  0.2   0:10.20 sshd

top 快捷键

  • P → 按 CPU 使用率排序
  • M → 按内存使用率排序
  • k → 输入 PID 杀掉进程
  • q → 退出

5.3 管理进程

kill——终止进程

# 温柔终止(发送 SIGTERM 信号,让进程自行清理退出)
[root@server ~]# kill 1234

# 强制终止(发送 SIGKILL 信号,立刻杀死进程)
[root@server ~]# kill -9 1234

# 按名称杀进程(慎用!可能误杀)
[root@server ~]# pkill -f "python3 myscript.py"

# 杀掉某用户的所有进程
[root@server ~]# pkill -u alice

警告kill -9 是"核弹"——只在普通 kill 无效时使用。强制杀死进程可能导致数据丢失或文件损坏。

nice/renice——调整进程优先级

# nice 值范围:-20(最高优先级)到 19(最低优先级),默认 0

# 以较低优先级运行程序(不抢占其他进程的资源)
[root@server ~]# nice -n 10 tar czf backup.tar.gz /data/

# 修改已运行进程的优先级
[root@server ~]# renice -n 5 -p 1234

5.4 systemd 服务管理

类比:systemd 就像一个"物业管家"——它负责开机时自动启动各种服务(保安、清洁、电梯),并在服务出问题时尝试重启。

# 启动服务
[root@server ~]# systemctl start httpd

# 停止服务
[root@server ~]# systemctl stop httpd

# 重启服务
[root@server ~]# systemctl restart httpd

# 重新加载配置(不中断服务,推荐!)
[root@server ~]# systemctl reload httpd

# 查看服务状态
[root@server ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2024-03-15 10:30:00 CST; 2h ago
 Main PID: 5678 (httpd)
   CGroup: /system.slice/httpd.service

# 设置开机自启动
[root@server ~]# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service
to /usr/lib/systemd/system/httpd.service.

# 禁止开机自启动
[root@server ~]# systemctl disable httpd

# 查看所有正在运行的服务
[root@server ~]# systemctl list-units --type=service --state=running

# 查看服务的开机启动状态
[root@server ~]# systemctl is-enabled httpd
enabled

思考题:修改了 httpd 的配置文件后,应该用 restart 还是 reload?有什么区别?

答:优先用 reload。reload 只是重新加载配置文件,不会中断当前正在处理的请求;而 restart 会完全停止再启动服务,会导致正在访问的用户短暂断连。


第 6 章 软件管理

6.1 Linux 安装软件的三种方式

类比

  • yum:像手机应用商店——一键安装,自动处理依赖
  • rpm:像手动安装 .exe 程序——需要自己解决依赖关系
  • 源码编译:像买来食材自己做——最灵活,但最复杂

6.2 yum——最推荐的方式

# 搜索软件包
[root@server ~]# yum search httpd
Loaded plugins: fastestmirror
============================== N/S matched: httpd ==============================
httpd.x86_64 : Apache HTTP Server
httpd-tools.x86_64 : Tools for use with the Apache HTTP Server

# 安装软件包
[root@server ~]# yum install -y httpd
Loaded plugins: fastestmirror
Resolving Dependencies
--> Running transaction check
---> Package httpd.x86_64 0:2.4.6-97.el7.centos will be installed
--> Finished Dependency Resolution
Installed:
  httpd.x86_64 0:2.4.6-97.el7.centos
Complete!

# 卸载软件包
[root@server ~]# yum remove -y httpd

# 更新软件包
[root@server ~]# yum update -y httpd    # 只更新 httpd
[root@server ~]# yum update -y          # 更新所有软件(谨慎使用)

# 查看已安装的包
[root@server ~]# yum list installed | grep httpd
httpd.x86_64                    2.4.6-97.el7.centos                    @base

# 查看某个文件属于哪个包
[root@server ~]# yum provides /etc/httpd/conf/httpd.conf
httpd-2.4.6-97.el7.centos.x86_64 : Apache HTTP Server
Repo        : base
Matched from:
Filename    : /etc/httpd/conf/httpd.conf

# 清除缓存(解决"找不到包"的问题)
[root@server ~]# yum clean all
[root@server ~]# yum makecache

配置国内 yum 源(加速下载)

# 备份原始源
[root@server ~]# cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak

# 下载阿里云镜像源(CentOS 7)
[root@server ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo \
    https://mirrors.aliyun.com/repo/Centos-7.repo

# 刷新缓存
[root@server ~]# yum clean all && yum makecache

6.3 rpm——底层包管理

# 安装 rpm 包(-i 安装,-v 显示过程,-h 显示进度条)
[root@server ~]# rpm -ivh httpd-2.4.6-97.el7.centos.x86_64.rpm
error: Failed dependencies:        ← 缺少依赖
    apr >= 1.4.0 is needed by httpd-2.4.6-97.el7.centos.x86_64

# 查看已安装的包
[root@server ~]# rpm -qa | grep httpd
httpd-2.4.6-97.el7.centos.x86_64

# 查看包安装了哪些文件
[root@server ~]# rpm -ql httpd
/etc/httpd
/etc/httpd/conf
/etc/httpd/conf/httpd.conf
/usr/sbin/httpd
...

# 查看某个文件属于哪个 rpm 包
[root@server ~]# rpm -qf /etc/httpd/conf/httpd.conf
httpd-2.4.6-97.el7.centos.x86_64

# 卸载
[root@server ~]# rpm -e httpd

# 强制安装(忽略依赖,不推荐)
[root@server ~]# rpm -ivh --nodeps xxx.rpm

6.4 源码编译安装——了解即可

# 源码编译三步曲(几乎所有 Linux 源码包都遵循)

# 第 1 步:配置(检查环境,生成编译脚本)
[root@server ~]# tar xf nginx-1.20.1.tar.gz
[root@server ~]# cd nginx-1.20.1
[root@server nginx-1.20.1]# ./configure --prefix=/usr/local/nginx

# 第 2 步:编译(把源码变成可执行文件)
[root@server nginx-1.20.1]# make

# 第 3 步:安装(把编译好的文件复制到指定目录)
[root@server nginx-1.20.1]# make install

思考题:为什么生产环境中更推荐用 yum 而不是 rpm 来安装软件?

答:因为 yum 能自动解决依赖关系。一个软件可能依赖其他十几个库,rpm 需要手动一个个安装,而 yum 会自动下载并安装所有依赖。


第 7 章 Shell 高级命令

7.1 为什么需要 Shell 高级命令?

问题:服务器的日志文件有几十万行,怎么快速找到报错信息?怎么统计网站每天的访问量?

Shell 高级命令是服务器运维的"瑞士军刀"——grep 搜索、awk 分析、sed 批量修改、sort 排序,组合起来威力巨大。

7.2 grep——文本搜索利器

# 在文件中搜索关键词
[root@server ~]# grep "error" /var/log/messages
Mar 15 10:30:00 server kernel: EXT4-fs error (device sda1): ...
Mar 15 10:31:00 server sshd[1234]: error: Received disconnect ...

# -i 忽略大小写
[root@server ~]# grep -i "ERROR" /var/log/messages

# -n 显示行号
[root@server ~]# grep -n "error" /var/log/messages
1025:Mar 15 10:30:00 server kernel: EXT4-fs error ...

# -v 反向搜索(排除某个关键词)
[root@server ~]# grep -v "info" /var/log/messages

# -c 统计匹配行数
[root@server ~]# grep -c "error" /var/log/messages
42

# -r 递归搜索整个目录
[root@server ~]# grep -r "listen" /etc/httpd/
/etc/httpd/conf/httpd.conf:Listen 80

# 使用正则表达式
[root@server ~]# grep "^[0-9]" /etc/passwd        # 以数字开头的行
[root@server ~]# grep "bash$" /etc/passwd          # 以 bash 结尾的行
[root@server ~]# grep -E "error|warning" /var/log/messages  # 搜索多个关键词

7.3 cut——按列切割

# 提取 /etc/passwd 的用户名(第1列)
[root@server ~]# cut -d: -f1 /etc/passwd
root
bin
daemon
adm

# 提取用户名和 Shell(第1列和第7列)
[root@server ~]# cut -d: -f1,7 /etc/passwd
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin

# -d  指定分隔符(默认是Tab)
# -f  指定取第几列

7.4 sort——排序

# 按字母排序
[root@server ~]# sort /etc/passwd
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
...

# -t 指定分隔符,-k 指定按第几列排序
[root@server ~]# sort -t: -k3 -n /etc/passwd
# -n 按数字大小排序(而不是按字符排序)
# 按 UID(第3列)从小到大排序

# -r 逆序排列
[root@server ~]# sort -t: -k3 -rn /etc/passwd

# -u 去重
[root@server ~]# sort -u file.txt

7.5 uniq——去重和统计

# 注意:uniq 只能去除相邻的重复行,所以通常先 sort 再 uniq

# 统计每种日志级别出现的次数
[root@server ~]# cut -d' ' -f5 /var/log/messages | sort | uniq -c | sort -rn
   1523 INFO
    342 WARNING
     45 ERROR
     12 CRITICAL

7.6 wc——统计行、词、字节

# 统计文件行数
[root@server ~]# wc -l /etc/passwd
45 /etc/passwd

# 统计单词数
[root@server ~]# wc -w /etc/hosts
32 /etc/hosts

# 统计字节数
[root@server ~]# wc -c /etc/hostname
20 /etc/hostname

# 实战:统计系统中有多少个用户可以登录
[root@server ~]# grep -v "nologin\|false" /etc/passwd | wc -l
5

7.7 awk——强大的文本分析工具

# awk 的基本语法:awk '条件 {动作}' 文件

# 打印 /etc/passwd 中的用户名和家目录
[root@server ~]# awk -F: '{print $1, $6}' /etc/passwd
root /root
bin /bin
daemon /sbin
alice /home/alice

# -F:  以冒号分隔
# $1   第1列
# $6   第6列

# 打印 UID 大于 1000 的用户
[root@server ~]# awk -F: '$3 > 1000 {print $1, $3}' /etc/passwd
alice 1001
bob 1002

# 打印所有使用 bash 的用户
[root@server ~]# awk -F: '$7 == "/bin/bash" {print $1}' /etc/passwd
root
alice

# 统计 /etc/passwd 中各 Shell 的用户数
[root@server ~]# awk -F: '{shell[$7]++} END {for(s in shell) print shell[s], s}' /etc/passwd
25 /sbin/nologin
5 /bin/bash
1 /bin/sync

# 计算磁盘总使用量(取 df 输出的第3列)
[root@server ~]# df -h | awk 'NR>1 {sum+=$3} END {print "Total used:", sum}'

7.8 sed——流编辑器(批量替换利器)

# 基本语法:sed '命令' 文件

# 替换文本(和 vim 的替换语法一样!)
[root@server ~]# sed 's/old/new/' file.txt         # 替换每行第一个匹配
[root@server ~]# sed 's/old/new/g' file.txt        # 替换每行所有匹配

# 删除行
[root@server ~]# sed '3d' file.txt                 # 删除第3行
[root@server ~]# sed '3,5d' file.txt               # 删除第3到5行
[root@server ~]# sed '/^#/d' /etc/httpd/conf/httpd.conf  # 删除所有注释行
[root@server ~]# sed '/^$/d' file.txt              # 删除所有空行

# 打印特定行
[root@server ~]# sed -n '10,20p' file.txt          # 只打印第10到20行

# 在特定行后插入文本
[root@server ~]# sed '3a\这是新插入的一行' file.txt

# 直接修改文件(-i 参数,慎用!建议先备份)
[root@server ~]# sed -i.bak 's/8080/9090/g' /etc/httpd/conf/httpd.conf
# 会先创建 .bak 备份文件,再修改

# 实战:批量修改配置文件中的 IP 地址
[root@server ~]# sed -i 's/192\.168\.1\.100/192.168.1.200/g' /etc/myapp.conf

7.9 管道与重定向——组合威力

# 管道(|):把前一个命令的输出传给后一个命令
# 例:查看占用内存最多的前10个进程
[root@server ~]# ps aux --sort=-%mem | head -11

# 输出重定向(>):把输出保存到文件
[root@server ~]# echo "Hello" > /tmp/test.txt       # 覆盖写入
[root@server ~]# echo "World" >> /tmp/test.txt      # 追加写入

# 错误重定向(2>):把错误信息保存到文件
[root@server ~]# find / -name "*.conf" 2>/dev/null  # 丢弃错误信息

# 同时重定向标准输出和错误输出
[root@server ~]# command > output.log 2>&1

# 实战:统计每台服务器的连接数
[root@server ~]# ss -tn | awk 'NR>1 {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn
     15 192.168.1.100
      8 192.168.1.101
      3 10.0.0.50

思考题:如何快速找出系统中 UID 最大的普通用户(UID>=1000)?

awk -F: '$3 >= 1000 {print $1, $3}' /etc/passwd | sort -k2 -rn | head -1

第 8 章 磁盘管理

8.1 磁盘的基本概念

类比:一块新硬盘就像一块空地——你需要先划好地块(分区),铺好地板(格式化),然后挂上门牌号(挂载)才能使用。

硬盘类型:

  • SATA:串口硬盘(传统机械硬盘居多)
  • SSD:固态硬盘(速度快)
  • SCSI/SAS:服务器专用硬盘

设备命名规则:

/dev/sda     第一块 SATA/SCSI 硬盘
/dev/sda1    第一块硬盘的第1个分区
/dev/sda2    第一块硬盘的第2个分区
/dev/sdb     第二块硬盘
/dev/nvme0n1 第一块 NVMe 固态硬盘

8.2 查看磁盘信息

# 查看所有磁盘和分区
[root@server ~]# fdisk -l

Disk /dev/sda: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
/dev/sda2         1026048    41943039    20458496   8e  Linux LVM

Disk /dev/sdb: 10.7 GB, 10737418240 bytes, 20971520 sectors
# 新加的硬盘还没有分区

# 查看磁盘使用情况
[root@server ~]# df -hT
Filesystem              Type      Size  Used Avail Use% Mounted on
/dev/mapper/centos-root xfs        17G  2.1G   15G  13% /
/dev/sda1               xfs       497M  125M  373M  26% /boot

8.3 磁盘分区——fdisk

# 对新硬盘 /dev/sdb 进行分区
[root@server ~]# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).

Command (m for help): n          ← 新建分区
Partition type:
   p   primary (1-4)            ← p = 主分区
   e   extended                 ← e = 扩展分区
Select (default p): p            ← 选择主分区
Partition number (1-4, default 1): 1   ← 第1个分区
First sector (2048-20971519, default 2048):   ← 回车用默认值
Last sector, +sectors or +size{K,M,G} (2048-20971519, default 20971519): +5G
                                 ← 分区大小为 5GB

Command (m for help): w          ← 保存并退出
The partition table has been altered!

分区表类型:

  • msdos/MBR:最多 4 个主分区(或 3 主 + 1 扩展),最大支持 2TB
  • GPT:最多 128 个分区,支持大于 2TB 的硬盘

8.4 格式化——mkfs

# 格式化为 xfs 文件系统(CentOS 7 默认)
[root@server ~]# mkfs.xfs /dev/sdb1
meta-data=/dev/sdb1     isize=512    agcount=4, agsize=327680 blks
data   =               bsize=4096   blocks=1310720, imaxpct=25

# 格式化为 ext4 文件系统
[root@server ~]# mkfs.ext4 /dev/sdb1

# 查看文件系统类型
[root@server ~]# blkid /dev/sdb1
/dev/sdb1: UUID="a1b2c3d4-..." TYPE="xfs"

8.5 挂载与卸载

# 创建挂载点
[root@server ~]# mkdir /data

# 挂载分区
[root@server ~]# mount /dev/sdb1 /data

# 验证
[root@server ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1       5.0G   33M  5.0G   1% /data

# 卸载
[root@server ~]# umount /data
# 注意:如果有进程正在使用该挂载点,umount 会失败
# 解决:fuser -km /data  杀掉占用进程,然后再 umount

8.6 开机自动挂载——/etc/fstab

问题:mount 命令重启后就失效了,怎么让分区开机自动挂载?

# 编辑 /etc/fstab
[root@server ~]# vim /etc/fstab

# 添加一行:
# 设备               挂载点    类型  选项       dump  fsck
/dev/sdb1           /data     xfs   defaults   0     0

# 也可以用 UUID(更可靠,推荐)
UUID=a1b2c3d4-xxxx  /data     xfs   defaults   0     0

# 各字段说明:
# 第1列:设备路径或UUID
# 第2列:挂载点
# 第3列:文件系统类型(xfs, ext4, swap 等)
# 第4列:挂载选项(defaults 表示使用默认选项)
# 第5列:是否备份(0=不备份)
# 第6列:是否检测(0=不检测,1=最先检测,2=稍后检测)

# 测试 fstab 是否正确(重要!写错了可能导致无法开机)
[root@server ~]# mount -a
# 如果没有报错,说明配置正确

警告:编辑 /etc/fstab 前一定先用 mount -a 测试。如果 fstab 写错,系统重启后可能无法正常启动!

8.7 LVM 逻辑卷管理——灵活的磁盘方案

类比:传统分区像固定大小的储物柜——一旦做大了就改不了;LVM 像可拼装的积木——随时可以加一块、减一块。

LVM 三层结构:

物理卷(PV) → 把硬盘/分区变成 LVM 的"原材料"
     ↓
卷组(VG)   → 把多个 PV 合成一个大"池子"
     ↓
逻辑卷(LV) → 从"池子"里划出空间来用(相当于分区)
# 第 1 步:创建物理卷
[root@server ~]# pvcreate /dev/sdb1 /dev/sdc1
  Physical volume "/dev/sdb1" successfully created.

# 第 2 步:创建卷组
[root@server ~]# vgcreate datavg /dev/sdb1 /dev/sdc1
  Volume group "datavg" successfully created

# 第 3 步:创建逻辑卷(从卷组中划出 8GB)
[root@server ~]# lvcreate -L 8G -n datalv datavg
  Logical volume "datalv" created.

# 第 4 步:格式化并挂载
[root@server ~]# mkfs.xfs /dev/datavg/datalv
[root@server ~]# mount /dev/datavg/datalv /data

# 扩容逻辑卷(LVM 的最大优势!)
[root@server ~]# lvextend -L +2G /dev/datavg/datalv    # 增加 2GB
[root@server ~]# xfs_growfs /dev/datavg/datalv          # xfs 在线扩容
# 如果是 ext4:resize2fs /dev/datavg/datalv

# 查看 LVM 信息
[root@server ~]# pvs          # 查看物理卷
[root@server ~]# vgs          # 查看卷组
[root@server ~]# lvs          # 查看逻辑卷

思考题:服务器运行一段时间后 /data 空间不足了,但服务器不能停机。传统分区能在线扩容吗?LVM 呢?

答:传统分区不能在线扩容(需要重新分区,数据会丢失)。LVM 可以在线扩容——只需卷组里还有剩余空间,就能用 lvextendxfs_growfs 在线扩展,不需要停机。


第 9 章 网络管理

9.1 网络基础概念

类比:IP 地址就像你家的门牌号,子网掩码决定你家小区的范围,网关是小区大门的保安,DNS 是电话簿(把名字翻译成门牌号)。

关键概念:

概念作用类比
IP 地址设备在网络中的唯一标识门牌号
子网掩码确定网络范围小区边界
网关通往其他网络的出口小区大门
DNS把域名翻译成 IP 地址电话簿

9.2 查看和配置网络

查看网络信息

# ifconfig(传统命令,逐渐被 ip 取代)
[root@server ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.100  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::xxxx  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:xx:xx:xx  txqueuelen 1000  (Ethernet)

# ip addr(推荐,信息更详细)
[root@server ~]# ip addr show
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
    link/ether 00:0c:29:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.100/24 brd 192.168.1.255 scope global ens33
    inet6 fe80::xxxx/64 scope link

# 查看路由表
[root@server ~]# ip route show
default via 192.168.1.1 dev ens33 proto static metric 100
192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.100 metric 100

# 查看 DNS 配置
[root@server ~]# cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 114.114.114.114

使用 nmcli 配置网络(CentOS 7/8 推荐)

# 查看网络连接
[root@server ~]# nmcli connection show
NAME    UUID                                  TYPE      DEVICE
ens33   12345678-1234-1234-1234-123456789012  ethernet  ens33

# 配置静态 IP 地址
[root@server ~]# nmcli connection modify ens33 \
    ipv4.method manual \
    ipv4.addresses 192.168.1.100/24 \
    ipv4.gateway 192.168.1.1 \
    ipv4.dns "8.8.8.8,114.114.114.114" \
    connection.autoconnect yes

# 重启连接使配置生效
[root@server ~]# nmcli connection up ens33

# 也可以用 ip 命令临时配置(重启失效)
[root@server ~]# ip addr add 192.168.1.200/24 dev ens33
[root@server ~]# ip route add default via 192.168.1.1

修改配置文件方式

# 编辑网卡配置文件
[root@server ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33
TYPE=Ethernet
BOOTPROTO=static         # static=静态IP, dhcp=自动获取
NAME=ens33
DEVICE=ens33
ONBOOT=yes               # 开机是否启用
IPADDR=192.168.1.100     # IP地址
NETMASK=255.255.255.0    # 子网掩码
GATEWAY=192.168.1.1      # 网关
DNS1=8.8.8.8             # 主DNS
DNS2=114.114.114.114     # 备DNS

# 重启网络服务
[root@server ~]# systemctl restart network

9.3 网络排错

# 第 1 步:测试本机网络协议栈是否正常
[root@server ~]# ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.042 ms

# 第 2 步:测试能不能到网关
[root@server ~]# ping 192.168.1.1

# 第 3 步:测试能不能到外网 IP
[root@server ~]# ping 8.8.8.8

# 第 4 步:测试 DNS 解析是否正常
[root@server ~]# ping www.baidu.com

# 第 5 步:查看端口是否被监听
[root@server ~]# ss -tlnp
State      Recv-Q Send-Q Local Address:Port   Peer Address:Port  Process
LISTEN     0      128    *:22                  *:*                users:(("sshd",pid=520,fd=3))
LISTEN     0      128    :::80                 :::*               users:(("httpd",pid=5678,fd=4))

# 第 6 步:追踪路由路径
[root@server ~]# traceroute www.baidu.com

思考题:你能 ping 通网关(192.168.1.1),但 ping 不通 www.baidu.com,可能是什么原因?

答:两种可能——(1)DNS 配置有问题,检查 /etc/resolv.conf;(2)网关没有正确配置路由/防火墙限制了外网访问。先 ping 一个外网 IP(如 8.8.8.8),如果通了就是 DNS 问题。

9.4 防火墙基础(firewalld)

# 查看防火墙状态
[root@server ~]# firewall-cmd --state
running

# 查看已开放的端口
[root@server ~]# firewall-cmd --list-all

# 开放端口(如开放 80 端口做 Web 服务)
[root@server ~]# firewall-cmd --permanent --add-port=80/tcp
[root@server ~]# firewall-cmd --reload

# 关闭防火墙(仅在实验环境中使用!)
[root@server ~]# systemctl stop firewalld
[root@server ~]# systemctl disable firewalld

第 10 章 内核模块管理

10.1 什么是内核模块?

类比:内核模块就像手机的 APP——内核是手机系统,模块是按需加载的功能。你不需要把所有 APP 都预装在系统里,用到的时候再加载就行。

Linux 内核模块(kernel module)是可以在运行时动态加载和卸载的代码片段,通常用于驱动程序(网卡、显卡、文件系统等)。

10.2 模块管理命令

# 查看已加载的模块
[root@server ~]# lsmod
Module                  Size  Used by
xfs                   974848  3
bridge                151336  0
stp                    12976  1 bridge
...

# 输出三列:模块名、大小、被谁使用

# 查看某个模块的详细信息
[root@server ~]# modinfo e1000
filename:       /lib/modules/3.10.0-1062.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000/e1000.ko.xz
version:        7.3.21-k8-NAPI
license:        GPL
description:    Intel(R) PRO/1000 Network Driver
author:         Intel Corporation

# 加载模块
[root@server ~]# modprobe e1000

# 卸载模块(必须先确认没有进程在使用它)
[root@server ~]# modprobe -r e1000

# 搜索可用模块
[root@server ~]# find /lib/modules/$(uname -r) -name "*.ko*" | grep -i usb

# 查看模块依赖关系
[root@server ~]# modprobe --show-depends e1000

10.3 常见模块操作场景

# 场景:新装了一块网卡,但系统没识别
# 解决:手动加载对应的网卡驱动模块
[root@server ~]# lspci | grep -i ethernet     # 先查看硬件信息
00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller
[root@server ~]# modprobe e1000               # 加载对应驱动

# 场景:禁止加载某个模块(比如禁用 USB 存储,提高安全性)
[root@server ~]# echo "blacklist usb-storage" >> /etc/modprobe.d/blacklist.conf

# 查看操作系统的详细版本信息
[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

思考题modprobeinsmod 都能加载模块,它们有什么区别?

答:modprobe 会自动处理模块的依赖关系(如果一个模块依赖其他模块,会自动加载);insmod 只加载指定的单个模块文件,不会自动处理依赖。日常使用中推荐 modprobe


第二部分:Linux 基础服务


第 11 章 计划任务

11.1 为什么需要计划任务?

问题:服务器需要每天凌晨 3 点自动备份数据库、每周清理一次临时文件、每小时检查一次网站是否正常——你总不能半夜起来手动操作吧?

类比:计划任务就像"定时闹钟"——你设好时间和要做的事,到点了系统自动执行。

11.2 systemctl——服务管理基础

在配置计划任务之前,先回顾服务管理的基本操作:

# 通用格式:systemctl 操作 服务名

systemctl start    crond       # 启动服务
systemctl stop     crond       # 停止服务
systemctl restart  crond       # 重启服务
systemctl reload   crond       # 重新加载配置
systemctl enable   crond       # 设置开机自启
systemctl disable  crond       # 取消开机自启
systemctl status   crond       # 查看状态
systemctl is-enabled crond     # 查看是否已设开机自启

11.3 crontab——周期性计划任务

crontab 是 Linux 最常用的定时任务工具,几乎每台服务器都在用。

crontab 时间格式

*  *  *  *  *  命令
│  │  │  │  │
│  │  │  │  └── 星期几(0-7,0和7都是星期日)
│  │  │  └───── 月份(1-12)
│  │  └──────── 日期(1-31)
│  └─────────── 小时(0-23)
└────────────── 分钟(0-59)

特殊符号含义:

符号含义示例
*每个值(每分钟/每小时/每天...)* * * * * 每分钟执行
,指定多个值0 8,12,18 * * * 每天 8/12/18 点执行
-范围0 9-17 * * * 每天 9 到 17 点每小时执行
/间隔*/10 * * * * 每 10 分钟执行

常用 crontab 示例

# 编辑当前用户的 crontab
[root@server ~]# crontab -e

# 添加以下任务:

# 每天凌晨 3 点备份数据库
0 3 * * * /usr/bin/mysqldump -u root -p123456 mydb > /backup/db_$(date +\%F).sql

# 每 5 分钟检查网站是否正常
*/5 * * * * curl -s http://localhost > /dev/null || echo "网站挂了!" | mail -s "报警" admin@example.com

# 每周一早上 8 点清理日志
0 8 * * 1 find /var/log -name "*.log" -mtime +30 -delete

# 每月 1 号零点归档数据
0 0 1 * * tar czf /backup/archive_$(date +\%Y\%m).tar.gz /data/

# 保存退出后,查看当前用户的计划任务
[root@server ~]# crontab -l
0 3 * * * /usr/bin/mysqldump ...

# 删除当前用户的所有计划任务(慎用!)
[root@server ~]# crontab -r

# 查看其他用户的计划任务(需要 root 权限)
[root@server ~]# crontab -u alice -l

crontab 注意事项

# 1. 确保 crond 服务正在运行
[root@server ~]# systemctl status crond
[root@server ~]# systemctl enable crond

# 2. crontab 中的路径要写绝对路径!
#    错误:0 3 * * * backup.sh
#    正确:0 3 * * * /root/scripts/backup.sh

# 3. crontab 的环境变量和终端不同
#    建议在脚本开头加上:
#    #!/bin/bash
#    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# 4. date 命令中的 % 在 crontab 中要转义为 \%
#    0 3 * * * /bin/tar czf /backup/$(date +\%F).tar.gz /data/

# 5. crontab 日志(排查"为什么定时任务没执行")
[root@server ~]# tail -f /var/log/cron

11.4 at——一次性定时任务

# at 适合"只执行一次"的任务

# 10 分钟后执行
[root@server ~]# at now + 10 minutes
at> systemctl restart httpd
at> <EOT>                    ← 按 Ctrl+D 结束输入
job 3 at Mon Mar 15 15:00:00 2024

# 指定时间执行
[root@server ~]# at 23:00
at> shutdown -h now
at> <EOT>

# 查看等待执行的 at 任务
[root@server ~]# atq
3       Mon Mar 15 15:00:00 2024 a root

# 删除 at 任务
[root@server ~]# atrm 3

思考题crontabat 分别适合什么场景?

答:crontab 适合周期性重复任务(每天备份、每小时检查);at 适合一次性任务(10 分钟后重启服务、今晚 11 点关机)。


第 12 章 SSH 远程管理

12.1 为什么需要 SSH?

问题:服务器放在机房里,你总不能每次都跑到机房去操作吧?

SSH(Secure Shell)是一种加密的远程登录协议,让你在自己的电脑上安全地操控远处的服务器。

类比:SSH 就像给服务器打了一个加密电话——你说的每一句话都被加密传输,即使有人窃听也听不懂内容。

12.2 SSH 基础配置

# SSH 服务端(被连接的机器)安装
[root@server ~]# yum install -y openssh-server

# SSH 客户端(你的电脑)安装
[root@server ~]# yum install -y openssh-clients

# 启动 SSH 服务
[root@server ~]# systemctl start sshd
[root@server ~]# systemctl enable sshd

# 默认端口:22

远程连接

# 基本连接
[user@client ~]$ ssh root@192.168.1.100

# 指定端口连接
[user@client ~]$ ssh -p 2222 root@192.168.1.100

# 执行远程命令(不进入交互模式)
[user@client ~]$ ssh root@192.168.1.100 "df -h"

# 远程复制文件(scp)
[user@client ~]$ scp /local/file.txt root@192.168.1.100:/remote/path/
# 复制目录要加 -r
[user@client ~]$ scp -r /local/dir root@192.168.1.100:/remote/path/

12.3 sshd_config——SSH 服务配置详解

SSH 的配置文件在 /etc/ssh/sshd_config,以下是服务器安全加固的常用配置:

[root@server ~]# vim /etc/ssh/sshd_config
# ===== 端口和协议 =====
Port 2222                      # 修改默认端口(避免被扫描)
Protocol 2                     # 只使用 SSH 协议版本 2(更安全)

# ===== 登录限制 =====
PermitRootLogin no             # 禁止 root 直接登录(安全加固!)
PermitRootLogin prohibit-password  # 或者:只允许密钥登录 root
PasswordAuthentication no      # 禁止密码登录(只用密钥)
MaxAuthTries 3                 # 最多尝试 3 次密码
LoginGraceTime 60              # 登录超时时间(秒)
MaxSessions 5                  # 最大并发会话数

# ===== 用户限制 =====
AllowUsers alice bob           # 只允许指定用户登录
DenyUsers hacker               # 禁止指定用户登录

# ===== 安全选项 =====
PermitEmptyPasswords no        # 禁止空密码登录
UseDNS no                      # 关闭 DNS 反向解析(加快登录速度)
X11Forwarding no               # 关闭 X11 转发(不需要图形界面转发)
# 修改配置后重启 SSH 服务
[root@server ~]# systemctl restart sshd

# 重要!修改 SSH 配置前,建议保持当前 SSH 会话不要断开
# 另开一个终端测试新配置,如果连不上还有当前会话可以修复

12.4 SSH 密钥认证——免密码登录

问题:密码登录有两个风险——(1)密码可能被暴力破解;(2)每次登录都要输密码很麻烦。

类比:密码认证相当于每次进门都对暗号;密钥认证相当于配了一把专属钥匙——只有你有这把钥匙,门自动认你。

# 第 1 步:在客户端生成密钥对
[user@client ~]$ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):   ← 回车用默认
Enter passphrase (empty for no passphrase):                      ← 设置密码或直接回车
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa.        ← 私钥(保管好!)
Your public key has been saved in /home/user/.ssh/id_rsa.pub.        ← 公钥(可以公开)

# 第 2 步:把公钥复制到服务器
[user@client ~]$ ssh-copy-id root@192.168.1.100
/usr/bin/ssh-copy-id: INFO: attempting to log in with your new key(s)
Number of key(s) added: 1
Now try logging into the machine, with: "ssh root@192.168.1.100"

# 第 3 步:测试免密码登录
[user@client ~]$ ssh root@192.168.1.100
# 不需要输密码就能登录了!

手动部署公钥的方法(当 ssh-copy-id 不可用时):

# 在客户端查看公钥内容
[user@client ~]$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB... user@client

# 在服务器上手动添加
[root@server ~]# mkdir -p ~/.ssh
[root@server ~]# chmod 700 ~/.ssh
[root@server ~]# echo "ssh-rsa AAAAB3..." >> ~/.ssh/authorized_keys
[root@server ~]# chmod 600 ~/.ssh/authorized_keys

12.5 SSH 安全加固清单

措施配置方法作用
修改默认端口Port 2222避开自动扫描
禁止 root 登录PermitRootLogin no防止 root 密码被暴力破解
使用密钥认证PasswordAuthentication no杜绝密码暴力破解
限制登录用户AllowUsers alice bob只让需要的人登录
限制登录 IP防火墙或 hosts.allow/deny只允许特定 IP 访问
设置超时断开ClientAliveInterval 3005分钟无操作自动断开
安装 fail2banyum install fail2ban自动封禁暴力破解的 IP

思考题:你修改了 SSH 端口为 2222 并禁止了 root 登录,但重启 SSH 后发现自己登不上去了。可能是什么原因?

答:(1)防火墙没有放行新端口 2222;(2)你用的是 root 账户登录,但已经禁止了 root 登录。解决方法:先用普通用户登录,再 su - 切换到 root。


第 13 章 日志服务

13.1 为什么日志如此重要?

类比:日志就像服务器的"监控录像"——出了问题可以回放查看是谁干的、什么时候发生的、具体报了什么错。

13.2 rsyslog——系统日志服务

rsyslog 是 CentOS 默认的日志收集服务,几乎所有系统日志都由它管理。

# 确保 rsyslog 正在运行
[root@server ~]# systemctl status rsyslog
[root@server ~]# systemctl enable rsyslog

配置文件 /etc/rsyslog.conf

[root@server ~]# vim /etc/rsyslog.conf

rsyslog 配置的核心格式:

设备.级别            日志文件路径

日志设备(Facility)——日志来自哪个子系统:

设备含义
auth认证相关(登录、sudo)
authpriv权限相关(ssh登录验证)
cron计划任务
daemon系统服务
kern内核
mail邮件
local0-local7自定义(8个保留设备)

日志级别(Severity)——从低到高:

级别数字含义
debug7调试信息
info6一般信息
notice5值得注意
warning/warn4警告
error/err3错误
crit2严重
alert1紧急
emerg/panic0系统不可用
# 配置示例(/etc/rsyslog.conf 中常见)
authpriv.*                  /var/log/secure       # 所有认证日志 → secure
*.info;mail.none;authpriv.none  /var/log/messages  # 一般信息 → messages
cron.*                      /var/log/cron          # 计划任务日志 → cron
mail.*                      /var/log/maillog       # 邮件日志 → maillog
*.emerg                     :omusrmsg:*            # 紧急消息 → 发给所有用户

# 自定义:把 local0 的日志写入单独文件
local0.*                    /var/log/myapp.log
# 修改配置后重启 rsyslog
[root@server ~]# systemctl restart rsyslog

常见日志文件

日志文件内容排查场景
/var/log/messages系统综合日志各种系统问题的首选排查对象
/var/log/secure安全认证日志查看谁在尝试登录
/var/log/cron计划任务日志定时任务没执行?看这里
/var/log/boot.log启动日志开机过程的问题
/var/log/maillog邮件日志邮件发送失败排查
/var/log/dmesg内核启动日志硬件问题排查

13.3 logrotate——日志轮转

问题:日志文件越来越大,迟早会占满磁盘空间。

类比:logrotate 就像"自动翻页的笔记本"——写满一页就翻到新的,旧页自动归档。

# logrotate 配置文件
[root@server ~]# cat /etc/logrotate.conf
# 全局默认设置
weekly                # 每周轮转一次
rotate 4              # 保留 4 个旧文件
create                # 轮转后创建新文件
dateext               # 旧文件加日期后缀

# 包含子配置
include /etc/logrotate.d

# 查看某个服务的轮转配置
[root@server ~]# cat /etc/logrotate.d/syslog
/var/log/messages
/var/log/secure
/var/log/maillog
{
    sharedscripts
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    endscript
}

# 自定义轮转配置(例:网站访问日志每天轮转,保留 30 天)
[root@server ~]# vim /etc/logrotate.d/myapp
/var/log/myapp/access.log {
    daily               # 每天轮转
    rotate 30           # 保留 30 个旧文件
    compress            # 压缩旧文件(节省空间)
    missingok           # 文件不存在也不报错
    notifempty          # 空文件不轮转
    create 0640 www www # 新文件的权限和所有者
    postrotate          # 轮转后执行的命令
        systemctl reload httpd
    endscript
}

# 手动测试轮转(不实际执行,只模拟)
[root@server ~]# logrotate -d /etc/logrotate.d/myapp

# 手动执行轮转
[root@server ~]# logrotate -f /etc/logrotate.d/myapp

思考题:你的服务器磁盘突然满了,df -h 显示 /var 使用了 99%。你会怎么排查?

答:(1)du -sh /var/log/* 查看哪个日志文件最大;(2)如果某个日志文件过大,用 > /var/log/xxx.log 清空它(不要用 rm,因为进程还在写入);(3)配置 logrotate 定期轮转,防止再次发生。


第 14 章 NFS 文件服务器

14.1 什么是 NFS?

NFS(Network File System,网络文件系统)让你像访问本地文件一样访问远程服务器上的文件。

类比:NFS 就像在办公室里装了共享文件夹——你把文件放在"柜子"(NFS 服务器)里,办公室里的每个人(客户端)都能直接打开和编辑。

用途

  • 多台服务器共享同一份数据(如网站静态文件)
  • 集中存储用户文件(如作业提交目录)
  • 增加存储空间(把远程硬盘"挂"到本地)

14.2 搭建 NFS 服务器

# 安装软件
[root@nfs-server ~]# yum install -y nfs-utils rpcbind

# 启动服务
[root@nfs-server ~]# systemctl start rpcbind
[root@nfs-server ~]# systemctl start nfs-server
[root@nfs-server ~]# systemctl enable rpcbind
[root@nfs-server ~]# systemctl enable nfs-server

# 创建共享目录
[root@nfs-server ~]# mkdir -p /data/share
[root@nfs-server ~]# chmod 777 /data/share

配置 /etc/exports

[root@nfs-server ~]# vim /etc/exports

# 格式:共享目录  允许的客户端(选项)

# 示例 1:允许 192.168.1.0/24 网段读写访问
/data/share    192.168.1.0/24(rw,sync,no_root_squash)

# 示例 2:允许特定 IP 只读访问
/data/share    192.168.1.100(ro,sync)

# 示例 3:允许所有主机读写(危险!仅实验环境)
/data/share    *(rw,sync)

常用选项说明:

选项含义
rw读写权限
ro只读权限
sync同步写入磁盘(数据安全,推荐)
async异步写入(速度快,但断电可能丢数据)
no_root_squash客户端 root 保持 root 权限(方便但不安全)
root_squash客户端 root 被映射为 nfsnobody(安全,默认)
all_squash所有用户都映射为 nfsnobody
anonuid=xxx指定映射的 UID
# 使 exports 配置生效(不需要重启服务)
[root@nfs-server ~]# exportfs -rv
exporting 192.168.1.0/24:/data/share

# 查看当前共享
[root@nfs-server ~]# exportfs -v
/data/share    192.168.1.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,no_root_squash)

# 开放防火墙端口
[root@nfs-server ~]# firewall-cmd --permanent --add-service=nfs
[root@nfs-server ~]# firewall-cmd --permanent --add-service=rpc-bind
[root@nfs-server ~]# firewall-cmd --permanent --add-service=mountd
[root@nfs-server ~]# firewall-cmd --reload

14.3 客户端挂载 NFS

# 安装客户端工具
[root@client ~]# yum install -y nfs-utils

# 查看服务器共享了哪些目录
[root@client ~]# showmount -e 192.168.1.200
Export list for 192.168.1.200:
/data/share 192.168.1.0/24

# 挂载 NFS 共享
[root@client ~]# mkdir -p /mnt/nfs
[root@client ~]# mount -t nfs 192.168.1.200:/data/share /mnt/nfs

# 验证
[root@client ~]# df -h
192.168.1.200:/data/share   17G  2.1G   15G  13% /mnt/nfs

# 测试读写
[root@client ~]# echo "Hello NFS" > /mnt/nfs/test.txt

# 开机自动挂载(/etc/fstab)
192.168.1.200:/data/share   /mnt/nfs   nfs   defaults,_netdev   0 0
# _netdev 选项:等网络准备好后再挂载(很重要!)

思考题:NFS 客户端挂载后,创建的文件所有者显示为 nobody,怎么解决?

答:这是因为默认开启了 root_squash,客户端 root 被映射成了 nfsnobody。两种解决方法:(1)在服务器的 exports 中加 no_root_squash;(2)使用 anonuid 指定映射的 UID,让两端 UID 一致。


第 15 章 DHCP 服务器

15.1 什么是 DHCP?

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)自动给网络中的设备分配 IP 地址。

类比:DHCP 就像酒店前台——你来了(设备接入网络),前台给你分配一个房间号(IP 地址),退房时房间号回收给下一位客人。

15.2 搭建 DHCP 服务器

# 安装软件
[root@server ~]# yum install -y dhcp

# DHCP 默认没有示例配置,从模板复制一份
[root@server ~]# cp /usr/share/doc/dhcp-4.2.5/dhcpd.conf.example /etc/dhcp/dhcpd.conf

配置 /etc/dhcp/dhcpd.conf

[root@server ~]# vim /etc/dhcp/dhcpd.conf
# ===== 全局配置 =====
option domain-name "example.com";          # 域名
option domain-name-servers 8.8.8.8, 114.114.114.114;  # DNS 服务器
default-lease-time 600;                    # 默认租约时间(秒)
max-lease-time 7200;                       # 最大租约时间(秒)

# ===== 作用域(子网配置)=====
subnet 192.168.1.0 netmask 255.255.255.0 {
    range 192.168.1.100 192.168.1.200;    # 可分配的 IP 范围
    option routers 192.168.1.1;           # 网关
    option subnet-mask 255.255.255.0;     # 子网掩码
    option broadcast-address 192.168.1.255;  # 广播地址
}

# ===== 固定 IP 分配(按 MAC 地址绑定)=====
host teacher-pc {
    hardware ethernet 00:0c:29:aa:bb:cc;   # 设备的 MAC 地址
    fixed-address 192.168.1.50;            # 固定分配的 IP
}
# 启动服务
[root@server ~]# systemctl start dhcpd
[root@server ~]# systemctl enable dhcpd

# 查看分配的租约信息
[root@server ~]# cat /var/lib/dhcpd/dhcpd.leases
lease 192.168.1.100 {
  starts 1 2024/03/15 02:30:00;
  ends 1 2024/03/15 02:40:00;
  binding state active;
  hardware ethernet 00:0c:29:xx:xx:xx;
}

# 开放防火墙
[root@server ~]# firewall-cmd --permanent --add-service=dhcp
[root@server ~]# firewall-cmd --reload

15.3 DHCP 工作流程

客户端                    DHCP服务器
  │                          │
  │──── DHCP Discover ─────>│  "有没有DHCP服务器?"
  │                          │
  │<─── DHCP Offer ─────────│  "我有!给你 192.168.1.100"
  │                          │
  │──── DHCP Request ──────>│  "好的,我要这个IP"
  │                          │
  │<─── DHCP ACK ───────────│  "确认!IP归你了"
  │                          │

思考题:如果同一网络中有两台 DHCP 服务器会怎样?

答:客户端会接受最先收到的 Offer,可能导致获取到错误的 IP 配置(错误的网关、DNS 等)。这就是"DHCP 欺骗"攻击的原理。所以在企业网络中要严格管控 DHCP 服务器。


第 16 章 Apache Web 服务器

16.1 Apache 是什么?

Apache(httpd)是全球最流行的 Web 服务器软件之一,负责把网页文件发送给访问者的浏览器。

类比:Apache 就像一个"餐厅服务员"——客人(浏览器)点菜(请求网页),服务员从厨房(服务器硬盘)把菜(HTML 文件)端给客人。

16.2 安装和基本配置

# 安装
[root@server ~]# yum install -y httpd

# 启动并设置开机自启
[root@server ~]# systemctl start httpd
[root@server ~]# systemctl enable httpd

# 开放防火墙
[root@server ~]# firewall-cmd --permanent --add-service=http
[root@server ~]# firewall-cmd --permanent --add-service=https
[root@server ~]# firewall-cmd --reload

核心配置文件

/etc/httpd/conf/httpd.conf          主配置文件
/etc/httpd/conf.d/*.conf            子配置目录(推荐在这里写自定义配置)
/var/www/html/                      网站文件存放目录(默认根目录)
/var/log/httpd/access_log           访问日志
/var/log/httpd/error_log            错误日志

httpd.conf 关键配置

[root@server ~]# vim /etc/httpd/conf/httpd.conf
# ===== 基础配置 =====
ServerRoot "/etc/httpd"              # 配置根目录
Listen 80                            # 监听端口
ServerName www.example.com:80        # 服务器名称
DocumentRoot "/var/www/html"         # 网站文件目录

# ===== 目录权限 =====
<Directory "/var/www/html">
    Options Indexes FollowSymLinks   # Indexes: 允许列出目录内容
    AllowOverride None               # 是否允许 .htaccess 覆盖
    Require all granted              # 允许所有人访问
</Directory>

# ===== 默认首页 =====
DirectoryIndex index.html index.php  # 默认首页文件

# ===== 日志配置 =====
ErrorLog "logs/error_log"            # 错误日志
CustomLog "logs/access_log" combined # 访问日志(combined 格式包含更多信息)

16.3 虚拟主机——一台服务器跑多个网站

问题:只有一台服务器,但要同时提供 www.math.comwww.physics.com 两个网站,怎么办?

# 基于域名的虚拟主机(最常用)
[root@server ~]# vim /etc/httpd/conf.d/vhosts.conf
# ===== 网站 1:www.math.com =====
<VirtualHost *:80>
    ServerName www.math.com
    DocumentRoot /var/www/math
    <Directory "/var/www/math">
        Require all granted
    </Directory>
    ErrorLog logs/math-error_log
    CustomLog logs/math-access_log combined
</VirtualHost>

# ===== 网站 2:www.physics.com =====
<VirtualHost *:80>
    ServerName www.physics.com
    DocumentRoot /var/www/physics
    <Directory "/var/www/physics">
        Require all granted
    </Directory>
    ErrorLog logs/physics-error_log
    CustomLog logs/physics-access_log combined
</VirtualHost>
# 创建网站目录和测试页面
[root@server ~]# mkdir -p /var/www/math /var/www/physics
[root@server ~]# echo "<h1>Welcome to Math Site!</h1>" > /var/www/math/index.html
[root@server ~]# echo "<h1>Welcome to Physics Site!</h1>" > /var/www/physics/index.html

# 设置 SELinux 上下文(如果 SELinux 开启的话)
[root@server ~]# semanage fcontext -a -t httpd_sys_content_t "/var/www/math(/.*)?"
[root@server ~]# semanage fcontext -a -t httpd_sys_content_t "/var/www/physics(/.*)?"
[root@server ~]# restorecon -Rv /var/www/math /var/www/physics

# 重启 Apache
[root@server ~]# systemctl restart httpd

# 在客户端 /etc/hosts 中配置域名解析(实验用)
192.168.1.100  www.math.com
192.168.1.100  www.physics.com

16.4 HTTPS 加密配置(SSL/TLS)

类比:HTTP 像明信片——路上谁都能看到内容;HTTPS 像密封信——只有收件人能打开。

# 安装 SSL 模块
[root@server ~]# yum install -y mod_ssl

# 生成自签名证书(实验用)
[root@server ~]# openssl req -x509 -nodes -days 365 \
    -newkey rsa:2048 \
    -keyout /etc/pki/tls/private/server.key \
    -out /etc/pki/tls/certs/server.crt

# 配置 SSL 虚拟主机
[root@server ~]# vim /etc/httpd/conf.d/ssl.conf
<VirtualHost *:443>
    ServerName www.math.com
    DocumentRoot /var/www/math

    SSLEngine on
    SSLCertificateFile /etc/pki/tls/certs/server.crt
    SSLCertificateKeyFile /etc/pki/tls/private/server.key

    <Directory "/var/www/math">
        Require all granted
    </Directory>
</VirtualHost>
[root@server ~]# systemctl restart httpd
# 现在可以通过 https://www.math.com 访问了

思考题:访问网站时出现 "403 Forbidden" 错误,可能是什么原因?

答:(1)文件权限不够,chmod 755 /var/www/html/chmod 644 /var/www/html/index.html;(2)SELinux 阻止了访问,用 restorecon 修复上下文或临时 setenforce 0 测试;(3)httpd.conf 中的目录权限设置了 Require all denied


第 17 章 DNS 域名解析服务器

17.1 DNS 是什么?

DNS(Domain Name System,域名系统)把人类好记的域名(如 www.baidu.com)翻译成计算机能识别的 IP 地址。

类比:DNS 就像电话簿——你知道对方的名字(域名),通过电话簿查到对方的电话号码(IP 地址),然后才能打电话(建立连接)。

17.2 DNS 解析过程

用户浏览器 → "www.example.com 的 IP 是什么?"
    ↓
本地 DNS 缓存 → 没有缓存
    ↓
/etc/hosts 文件 → 没有匹配
    ↓
配置的 DNS 服务器 → 查询并返回 IP
    ↓
浏览器用 IP 地址访问网站

17.3 搭建 DNS 服务器(BIND)

# 安装 BIND(DNS 服务器软件)
[root@server ~]# yum install -y bind bind-utils

# 启动服务
[root@server ~]# systemctl start named
[root@server ~]# systemctl enable named

主配置文件 /etc/named.conf

[root@server ~]# vim /etc/named.conf
options {
    listen-on port 53 { any; };          // 监听所有地址(生产环境建议限制)
    directory   "/var/named";             // 区域文件存放目录
    allow-query { any; };                 // 允许所有客户端查询
    recursion yes;                        // 允许递归查询
};

// 引入区域配置
include "/etc/named.rfc1912.zones";

区域配置 /etc/named.rfc1912.zones

[root@server ~]# vim /etc/named.rfc1912.zones
// 正向解析区域(域名 → IP)
zone "example.com" IN {
    type master;
    file "example.com.zone";
    allow-update { none; };
};

// 反向解析区域(IP → 域名)
zone "1.168.192.in-addr.arpa" IN {
    type master;
    file "192.168.1.rev";
    allow-update { none; };
};

正向解析区域文件

[root@server ~]# vim /var/named/example.com.zone
$TTL 1D
@       IN  SOA  ns1.example.com.  admin.example.com. (
                    2024031501  ; 序列号(每次修改后+1)
                    1D          ; 刷新时间
                    1H          ; 重试时间
                    1W          ; 过期时间
                    3H )        ; 最小 TTL

; NS 记录(名称服务器)
@       IN  NS   ns1.example.com.

; A 记录(域名 → IPv4)
ns1     IN  A    192.168.1.100
www     IN  A    192.168.1.100
mail    IN  A    192.168.1.101
ftp     IN  A    192.168.1.102

; MX 记录(邮件交换)
@       IN  MX  10  mail.example.com.

; CNAME 记录(别名)
blog    IN  CNAME  www.example.com.

反向解析区域文件

[root@server ~]# vim /var/named/192.168.1.rev
$TTL 1D
@       IN  SOA  ns1.example.com.  admin.example.com. (
                    2024031501
                    1D  1H  1W  3H )

@       IN  NS   ns1.example.com.

100     IN  PTR  ns1.example.com.
100     IN  PTR  www.example.com.
101     IN  PTR  mail.example.com.
102     IN  PTR  ftp.example.com.
# 设置区域文件权限
[root@server ~]# chown root:named /var/named/example.com.zone /var/named/192.168.1.rev
[root@server ~]# chmod 640 /var/named/example.com.zone /var/named/192.168.1.rev

# 检查配置文件语法
[root@server ~]# named-checkconf
[root@server ~]# named-checkzone example.com /var/named/example.com.zone
zone example.com/IN: loaded serial 2024031501
OK

# 重启服务
[root@server ~]# systemctl restart named

# 开放防火墙
[root@server ~]# firewall-cmd --permanent --add-service=dns
[root@server ~]# firewall-cmd --reload

17.4 测试 DNS 解析

# 指定 DNS 服务器进行查询
[root@client ~]# nslookup www.example.com 192.168.1.100
Server:     192.168.1.100
Address:    192.168.1.100#53

Name:   www.example.com
Address: 192.168.1.100

# 使用 dig 命令(更详细)
[root@client ~]# dig www.example.com @192.168.1.100

; <<>> DiG 9.11.4 <<>> www.example.com @192.168.1.100
;; ANSWER SECTION:
www.example.com.    86400   IN  A   192.168.1.100

# 查询 MX 记录
[root@client ~]# dig MX example.com @192.168.1.100

# 反向解析测试
[root@client ~]# nslookup 192.168.1.100 192.168.1.100
100.1.168.192.in-addr.arpa  name = www.example.com.

17.5 常见 DNS 记录类型

记录类型作用示例
A域名 → IPv4 地址www → 192.168.1.100
AAAA域名 → IPv6 地址www → 2001:db8::1
CNAME别名 → 正式域名blog → www.example.com
MX邮件服务器@ → mail.example.com
NS域名服务器@ → ns1.example.com
PTRIP → 域名(反向)100 → www.example.com
SOA区域起始授权包含序列号、刷新时间等

思考题:DNS 中的 MX 记录后面的数字(如 10)代表什么?

答:代表优先级。数字越小优先级越高。如果有多台邮件服务器,发件方会优先发给优先级最高的服务器。如果最高优先级的服务器不可用,会尝试下一台。


第 18 章 NTP 时间服务器

18.1 为什么时间同步很重要?

问题:如果你的服务器显示的时间比实际快了一小时,日志记录的时间就是错的,计划任务也会在错误的时间执行,证书可能因为时间不对而被拒绝。

类比:NTP 就像学校里的广播打铃系统——所有教室的钟都跟着中央时钟走,确保上下课时间一致。

18.2 时间相关基础操作

# 查看当前时间
[root@server ~]# date
Mon Mar 15 14:30:00 CST 2024

# 手动设置时间(不推荐,仅应急使用)
[root@server ~]# date -s "2024-03-15 14:30:00"

# 查看硬件时钟(BIOS 时间)
[root@server ~]# hwclock

# 同步硬件时钟到系统时间
[root@server ~]# hwclock -s        # BIOS → 系统
[root@server ~]# hwclock -w        # 系统 → BIOS

# 查看时区
[root@server ~]# timedatectl
      Local time: Mon 2024-03-15 14:30:00 CST
  Universal time: Mon 2024-03-15 06:30:00 UTC
        Time zone: Asia/Shanghai (CST, +0800)

# 修改时区
[root@server ~]# timedatectl set-timezone Asia/Shanghai

18.3 使用 ntpdate 同步时间(简单方式)

# 安装 ntpdate
[root@server ~]# yum install -y ntpdate

# 从公共 NTP 服务器同步一次
[root@server ~]# ntpdate ntp.aliyun.com
15 Mar 14:30:00 ntpdate[12345]: adjust time server 203.107.6.88 offset -0.001234 sec

# 常用公共 NTP 服务器
# ntp.aliyun.com      阿里云
# ntp.tencent.com     腾讯云
# cn.pool.ntp.org     NTP 中国
# time.windows.com    微软
# time.apple.com      苹果

18.4 使用 chrony 搭建 NTP 服务器(推荐方式)

chrony 是 CentOS 7/8 默认的 NTP 软件,比传统 ntpd 更快、更精确。

# 安装 chrony
[root@server ~]# yum install -y chrony

# 编辑配置
[root@server ~]# vim /etc/chrony.conf
# ===== 上游 NTP 服务器 =====
server ntp.aliyun.com iburst       # iburst = 初始快速同步
server ntp.tencent.com iburst
server cn.pool.ntp.org iburst

# ===== 允许客户端同步 =====
# 允许 192.168.1.0/24 网段的设备来同步时间
allow 192.168.1.0/24

# ===== 本地时钟作为备用 =====
# 当上游服务器都不可达时,使用本地时间作为参考
local stratum 10

# ===== 日志 =====
logdir /var/log/chrony
# 启动服务
[root@server ~]# systemctl start chronyd
[root@server ~]# systemctl enable chronyd

# 开放防火墙(NTP 使用 UDP 123 端口)
[root@server ~]# firewall-cmd --permanent --add-service=ntp
[root@server ~]# firewall-cmd --reload

# 查看同步状态
[root@server ~]# chronyc sources -v
210 Number of sources = 3

  MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* ntp.aliyun.com                  2   6   377    35    -12us[  -15us] +/-  23ms
^+ ntp.tencent.com                 2   6   377    33    +25us[  +22us] +/-  30ms
^- time.cloudflare.com             3   6   377    37   +150us[ +147us] +/-  80ms

# * 表示当前正在使用的上游服务器
# + 表示可用的候选服务器

# 查看时间同步详细信息
[root@server ~]# chronyc tracking
Reference ID    : CB6B0658 (ntp.aliyun.com)
Stratum         : 3
Ref time (UTC)  : Mon Mar 15 06:30:00 2024
System time     : 0.000001234 seconds fast of NTP time

18.5 客户端配置

# 客户端只需指向上面的 NTP 服务器
[root@client ~]# vim /etc/chrony.conf

# 把 server 改成你的 NTP 服务器地址
server 192.168.1.100 iburst

[root@client ~]# systemctl restart chronyd

# 验证同步
[root@client ~]# chronyc sources
210 Number of sources = 1
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 192.168.1.100                 3   6   377     5   +10us[  +10us] +/-  25ms

思考题:为什么企业内网要搭建自己的 NTP 服务器,而不是让每台电脑直接连公网 NTP?

答:(1)安全——内网设备不需要访问外网;(2)精确——内网延迟低,同步更准确;(3)可靠——即使外网断了,内网所有设备的时间仍然一致。


第 19 章 邮件服务器

19.1 邮件系统概述

类比:发邮件就像寄快递——你写好信(撰写邮件),交给邮局(SMTP 发送服务器),邮局按照地址投递到对方邮局(接收服务器),对方从自己的邮箱(POP3/IMAP)取出信件。

邮件系统涉及的协议:

协议作用端口类比
SMTP发送邮件25 (明文) / 465 (SSL) / 587 (TLS)寄快递
POP3接收邮件(下载到本地)110 / 995 (SSL)取快递带回家
IMAP接收邮件(同步服务器)143 / 993 (SSL)在快递柜查看

邮件系统的两个核心软件:

  • postfix:负责发送邮件(SMTP 服务器)
  • dovecot:负责接收邮件(POP3/IMAP 服务器)

19.2 搭建 Postfix 发送服务器

# 安装 postfix
[root@server ~]# yum install -y postfix

# 编辑配置
[root@server ~]# vim /etc/postfix/main.cf
# ===== 基本配置 =====
myhostname = mail.example.com          # 邮件服务器主机名
mydomain = example.com                 # 域名
myorigin = $mydomain                   # 发件人显示的域名
inet_interfaces = all                  # 监听所有网卡
inet_protocols = ipv4                  # 只用 IPv4

# ===== 邮件存储 =====
mydestination = $myhostname, $mydomain, localhost    # 接收邮件的域名
home_mailbox = Maildir/                # 邮件存储格式(推荐 Maildir)

# ===== 安全配置 =====
smtpd_banner = $myhostname ESMTP       # 服务器标识
smtpd_recipient_restrictions =         # 收件人限制
    permit_mynetworks,                 # 允许本网
    reject_unauth_destination          # 拒绝未授权转发
# 启动服务
[root@server ~]# systemctl start postfix
[root@server ~]# systemctl enable postfix

19.3 搭建 Dovecot 接收服务器

# 安装 dovecot
[root@server ~]# yum install -y dovecot

# 编辑主配置
[root@server ~]# vim /etc/dovecot/dovecot.conf
# 启用 IMAP 和 POP3 协议
protocols = imap pop3

# 监听所有地址
listen = *
# 配置邮件存储位置
[root@server ~]# vim /etc/dovecot/conf.d/10-mail.conf
# 邮件存储位置和格式(要和 postfix 一致)
mail_location = maildir:~/Maildir
# 配置认证
[root@server ~]# vim /etc/dovecot/conf.d/10-auth.conf
# 允许明文密码(仅实验环境!生产环境必须用 SSL)
disable_plaintext_auth = no

# 认证方式
auth_mechanisms = plain login
# 启动服务
[root@server ~]# systemctl start dovecot
[root@server ~]# systemctl enable dovecot

# 开放防火墙端口
[root@server ~]# firewall-cmd --permanent --add-port=25/tcp    # SMTP
[root@server ~]# firewall-cmd --permanent --add-port=110/tcp   # POP3
[root@server ~]# firewall-cmd --permanent --add-port=143/tcp   # IMAP
[root@server ~]# firewall-cmd --reload

19.4 测试邮件发送

# 方法1:使用 telnet 测试 SMTP
[root@server ~]# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
220 mail.example.com ESMTP
helo localhost
250 mail.example.com
mail from: alice@example.com
250 2.1.0 Ok
rcpt to: bob@example.com
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
Subject: Test Email
Hello Bob, this is a test email!
.
250 2.0.0 Ok: queued as ABCDEF
quit
221 2.0.0 Bye

# 方法2:使用 mail 命令(需要安装 mailx)
[root@server ~]# yum install -y mailx
[root@server ~]# echo "This is test content" | mail -s "Test Subject" bob@example.com

# 查看 Bob 的邮件
[root@server ~]# su - bob
[bob@server ~]$ ls ~/Maildir/new/
1710000000.V801I12345.server.example.com
[bob@server ~]$ cat ~/Maildir/new/1710000000.V801I12345.server.example.com

19.5 邮件服务器排错

# 查看 postfix 日志
[root@server ~]# tail -f /var/log/maillog
Mar 15 14:30:00 server postfix/smtpd[1234]: connect from unknown[192.168.1.50]
Mar 15 14:30:01 server postfix/smtpd[1234]: NOQUEUE: reject: RCPT from ...

# 查看邮件队列
[root@server ~]# mailq
Mail queue is empty

# 强制发送队列中的邮件
[root@server ~]# postqueue -f

# 清空邮件队列
[root@server ~]# postsuper -d ALL

思考题:你搭建的邮件服务器能发信到本地用户,但发不到外网邮箱(如 QQ 邮箱),可能是什么原因?

答:(1)DNS 的 MX 记录没有配置正确;(2)服务器的 25 端口被运营商/云服务商封了(很多云服务商默认封 25 端口防止发垃圾邮件);(3)没有配置 SPF/DKIM 记录,被对方服务器当成垃圾邮件拒绝了。


附录

附录 A:常用端口速查表

端口服务协议说明
20/21FTPTCP文件传输
22SSHTCP远程登录
23TelnetTCP远程登录(明文,不推荐)
25SMTPTCP邮件发送
53DNSUDP/TCP域名解析
67/68DHCPUDP自动分配 IP
80HTTPTCP网页服务
110POP3TCP邮件接收
123NTPUDP时间同步
143IMAPTCP邮件同步
443HTTPSTCP加密网页
2049NFSTCP/UDP网络文件系统
3306MySQLTCP数据库

附录 B:SELinux 快速指南

SELinux(Security-Enhanced Linux)是 CentOS 的安全增强机制。很多初学者因为它"莫名其妙"地阻止服务而直接关闭它。

# 查看 SELinux 状态
[root@server ~]# getenforce
Enforcing

# 临时关闭(重启恢复)
[root@server ~]# setenforce 0

# 永久关闭(不推荐,但实验环境可以)
[root@server ~]# vim /etc/selinux/config
SELINUX=disabled

# 查看 SELinux 阻止了什么
[root@server ~]# grep "denied" /var/log/audit/audit.log

# 修复文件的安全上下文
[root@server ~]# restorecon -Rv /var/www/html/

# 修改端口允许(如让 Apache 监听 8080 端口)
[root@server ~]# semanage port -a -t http_port_t -p tcp 8080

附录 C:常见故障排查流程图

服务无法访问?
├── 1. 服务启动了吗?
│   └── systemctl status 服务名
├── 2. 端口在监听吗?
│   └── ss -tlnp | grep 端口号
├── 3. 防火墙放行了吗?
│   └── firewall-cmd --list-all
├── 4. SELinux 阻止了吗?
│   └── setenforce 0 试试(测试用)
├── 5. 网络通吗?
│   └── ping 服务器IP
└── 6. 看日志!
    └── tail -f /var/log/相关日志

附录 D:学习建议

  1. 一定要动手:光看不练等于没学。用 VirtualBox 或 VMware 装一个 CentOS 虚拟机
  2. 先装最小化系统:不要装图形界面,逼自己用命令行
  3. 养成看日志的习惯:出了问题先看 /var/log/messages 和相关服务的日志
  4. 做快照:在虚拟机里做危险操作前先打快照,搞坏了可以回滚
  5. 从搭建一个网站开始:把 Apache + DNS + 防火墙都走一遍,会串联起很多知识点

文档版本:v1.0 | 适用系统:CentOS 7/8, RHEL 7/8, Rocky Linux, AlmaLinux

编写说明:本文档面向高中信息技术教学,以实战为导向,覆盖了 Linux 服务器运维的核心知识点。建议配合虚拟机实验使用。