Comprehensive Study Notes

Linux
完整知识体系

从文件系统到内核调优,覆盖 Linux 全部核心知识点、运维难点与高频易错陷阱。适用于系统管理员、后端开发者及 DevOps 工程师。

CHAPTERS 24
COMMANDS 400+
DISTRO CentOS / Ubuntu / Debian
01

系统概述与哲学

1.1 Linux 核心哲学

  • 一切皆文件 — 硬件、进程、网络套接字都通过文件接口访问
  • 小而美 — 每个程序只做一件事,做好一件事
  • 组合优于单体 — 通过管道 | 组合简单工具完成复杂任务
  • 文本为王 — 配置文件几乎都是纯文本
  • 透明性 — 系统行为可观察、可调试、可预测

1.2 系统架构概览

# Linux 系统层次
┌─────────────────────────────────┐
│     用户空间 (User Space)         │  ← 应用程序、Shell、服务
├─────────────────────────────────┤
│     系统调用接口 (System Call)    │  ← open(), read(), write(), fork()
├─────────────────────────────────┤
│     内核 (Kernel)                │  ← 进程调度、内存管理、VFS、网络栈
├─────────────────────────────────┤
│     硬件抽象层 (HAL)             │  ← 驱动程序
├─────────────────────────────────┤
│     硬件 (Hardware)              │  ← CPU、内存、磁盘、网卡
└─────────────────────────────────┘

1.3 常见发行版

分支代表包管理适用场景
Debian 系Ubuntu, Debian, Mintapt / dpkg桌面、云服务器
RHEL 系CentOS, Rocky, Almayum / dnf企业服务器
Arch 系Arch, Manjaropacman极客、滚动更新
AlpineAlpine Linuxapk容器镜像
02

文件系统与目录

2.1 目录层次标准 (FHS)

# Linux 目录树结构
/
├── bin      → 基本用户命令 (ls, cp, mv)
├── sbin     → 系统管理命令 (fdisk, iptables)
├── etc      → 系统配置文件
├── home     → 用户主目录
├── root     → root 用户主目录
├── var      → 可变数据 (日志、缓存、数据库)
│   ├── log
│   ├── cache
│   └── tmp
├── tmp      → 临时文件(重启可能清空)
├── usr      → 用户级程序和数据(只读)
│   ├── bin
│   ├── lib
│   └── share
├── opt      → 第三方软件安装目录
├── proc     → 虚拟文件系统(进程信息)
├── sys      → 虚拟文件系统(设备/内核信息)
├── dev      → 设备文件 (硬盘、终端)
├── mnt      → 临时挂载点
├── boot     → 启动文件(内核、grub)
├── lib      → 共享库文件
└── media    → 可移动设备挂载点

2.2 文件系统类型

文件系统特点适用场景
ext4成熟稳定,支持日志通用 Linux 默认
xfs高性能,适合大文件数据库、大容量存储
btrfs快照、压缩、校验高级存储需求
tmpfs内存文件系统/tmp, /dev/shm
nfs网络文件系统网络共享存储
squashfs只读压缩Live CD、容器

2.3 inode 与硬链接/软链接

# inode 是文件的元数据(权限、大小、位置等),不包含文件名
ls -i file.txt              # 查看 inode 号
df -i                       # 查看 inode 使用情况

# 硬链接:同一 inode,多个文件名
ln file.txt hardlink.txt    # 硬链接

# 软链接(符号链接):独立文件,指向目标路径
ln -s file.txt symlink.txt  # 软链接
易错点 · 硬链接 vs 软链接
特性硬链接软链接
跨文件系统不可以可以
链接目录不可以可以
删除原文件仍可访问断链(红色闪烁)
inode相同不同
文件大小与原文件相同路径字符串长度

删除原文件后,硬链接数据仍然存在(inode 引用计数 > 0)。软链接会变成悬空引用。

03

文件与目录操作

3.1 导航与查看

pwd                              # 当前目录
cd /path/to/dir                  # 切换目录
cd -                             # 回到上一个目录
cd ~                             # 回到家目录

ls -la                           # 详细列表(含隐藏文件)
ls -lh                           # 人类可读的文件大小
ls -lt                           # 按修改时间排序
ls -lS                           # 按大小排序
tree -L 2                        # 树形结构(2层深度)

3.2 文件操作

# 创建
touch file.txt                   # 创建空文件 / 更新时间戳
mkdir -p /a/b/c                  # 递归创建目录
mktemp                           # 创建临时文件

# 复制
cp file.txt /backup/             # 复制文件
cp -r dir/ /backup/              # 递归复制目录
cp -a dir/ /backup/              # 归档复制(保留权限、时间戳、链接)
rsync -avz src/ dest/            # 增量同步(本地/远程)

# 移动 / 重命名
mv old.txt new.txt               # 重命名
mv file.txt /other/dir/          # 移动

# 删除(极度危险!)
rm file.txt                      # 删除文件
rm -r dir/                       # 递归删除目录
rm -rf dir/                      # 强制递归删除(不提示!)
rmdir empty_dir                  # 只删空目录
易错点 · rm -rf / 的灾难
# 永远不要执行(尤其是 root 下):
rm -rf /                         # 删除整个系统
rm -rf /*                        # 同上
rm -rf ~                         # 删除家目录

# 安全习惯:先 ls 再 rm
ls /tmp/to_delete/               # 先确认内容
rm -rf /tmp/to_delete/           # 再删除

# 加 -i 交互确认
rm -ri dir/                      # 每个文件都会确认

生产环境建议使用 trash-clitrash-put)代替 rm,给自己一个后悔的机会。

3.3 查找文件

# find — 最强大的文件查找
find / -name "*.log"                         # 按名称
find /var -type f -size +100M                # 大于100M的文件
find /tmp -mtime +7 -delete                  # 删除7天前的文件
find . -name "*.py" -exec grep -l "TODO" {} \;  # 查找含TODO的Python文件
find / -perm -4000                           # 查找 SUID 文件

# locate — 基于数据库的快速查找(需 updatedb)
locate nginx.conf

# which / whereis
which python3                   # 查找命令路径
whereis nginx                   # 查找命令、源码、手册

# type — 查看命令类型
type cd                         # cd is a shell builtin
type ls                         # ls is aliased to 'ls --color=auto'
04

权限与所有权

4.1 权限模型

# ls -l 输出解读
-rwxr-xr--  1  Ginc  devs  4096  Jan 15 10:30  script.sh
│└┬┘└┬┘└┬┘  │   │      │     │         │           │
│ │  │  │   │   │      │     │         │           └─ 文件名
│ │  │  │   │   │      │     │         └─ 修改时间
│ │  │  │   │   │      │     └─ 文件大小
│ │  │  │   │   │      └─ 所属组
│ │  │  │   │   └─ 所有者
│ │  │  │   └─ 硬链接数
│ │  │  └─ 其他用户 (r-- = 只读)
│ │  └─ 所属组 (r-x = 读+执行)
│ └─ 所有者 (rwx = 读+写+执行)
└─ 文件类型 (- 普通文件, d 目录, l 链接, c 字符设备, b 块设备)

4.2 chmod — 修改权限

# 数字模式(八进制)
chmod 755 script.sh              # rwxr-xr-x
chmod 644 config.txt             # rw-r--r--
chmod 600 secret.key             # rw-------
chmod 777 public/                # rwxrwxrwx(危险!)

# 符号模式
chmod u+x script.sh              # 给所有者加执行权限
chmod g-w file.txt               # 去掉组的写权限
chmod o=r file.txt               # 其他用户只读
chmod a+r file.txt               # 所有人加读权限
chmod -R 755 /var/www/           # 递归修改

# 常用权限速记
# 755 → 脚本/目录(所有者全权限,其他人读+执行)
# 644 → 配置文件(所有者读写,其他人只读)
# 600 → 私密文件(仅所有者读写)
# 700 → 私密目录(仅所有者访问)
难点 · 权限的数字计算
# r = 4, w = 2, x = 1  →  相加
# rwx = 4+2+1 = 7
# r-x = 4+0+1 = 5
# r-- = 4+0+0 = 4
# --- = 0+0+0 = 0

# 755 = rwx(7) r-x(5) r-x(5)
# 644 = rw-(6) r--(4) r--(4)

4.3 特殊权限位

权限符号数字作用示例
SUIDs (user x 位)4以文件所有者身份运行/usr/bin/passwd
SGIDs (group x 位)2以文件所属组身份运行;目录下新文件继承组共享目录
Sticky Bitt (other x 位)1只有所有者能删除自己的文件/tmp
chmod 4755 /usr/bin/myapp        # 设置 SUID
chmod 2755 /shared/              # 设置 SGID
chmod 1755 /tmp                  # 设置 Sticky Bit
find / -perm -4000 -ls           # 查找所有 SUID 文件(安全审计)

4.4 chown / chgrp

chown Ginc file.txt              # 修改所有者
chown Ginc:devs file.txt         # 同时修改所有者和组
chown :devs file.txt              # 只修改组
chown -R Ginc:devs /var/www/     # 递归修改
chgrp devs file.txt               # 修改所属组
易错点 · 目录的执行权限

目录的 x 权限表示能否进入(cd)该目录,而非执行。没有 x 权限的目录无法访问其中的任何文件,即使文件本身权限允许。r 权限只允许列出文件名,要真正读取文件内容还需要 x

05

用户与组管理

5.1 用户操作

# 创建用户
useradd -m -s /bin/bash -G sudo,docker Ginc  # 创建用户,指定shell和附加组
passwd Ginc                                    # 设置密码

# 修改用户
usermod -aG docker Ginc           # 追加到 docker 组(-a 必须!)
usermod -s /bin/zsh Ginc          # 修改默认 shell
usermod -L Ginc                   # 锁定账户
usermod -U Ginc                   # 解锁账户

# 删除用户
userdel Ginc                      # 删除用户(保留家目录)
userdel -r Ginc                   # 删除用户和家目录

# 查看用户信息
id Ginc                           # uid, gid, groups
whoami                             # 当前用户
who                                # 当前登录的所有用户
last                               # 最近登录记录
易错点 · usermod -aG

usermod -G docker Ginc(没有 -a)会覆盖所有附加组,只保留 docker!必须用 -aG 追加。这是一个非常常见的事故原因。

5.2 关键文件

文件内容格式
/etc/passwd用户信息name:x:uid:gid:comment:home:shell
/etc/shadow密码哈希仅 root 可读
/etc/group组信息name:x:gid:members
/etc/sudoerssudo 权限visudo 编辑

5.3 sudo

# /etc/sudoers 示例(用 visudo 编辑!)
Ginc  ALL=(ALL:ALL) ALL            # 完整 sudo 权限
bob    ALL=(ALL) NOPASSWD: ALL      # 免密 sudo
%devs  ALL=(ALL) /usr/bin/systemctl # devs 组只能用 systemctl
06

Shell 基础与变量

6.1 常见 Shell

Shell特点
bash最广泛,兼容 sh,Linux 默认
zsh更强的自动补全、主题支持(Oh My Zsh)
shPOSIX 标准,最基础
fish开箱即用的语法高亮、自动建议
dash轻量快速,Ubuntu 的 /bin/sh

6.2 变量

# 定义变量(等号两边不能有空格!)
name="Linux"                # 正确
name = "Linux"              # 错误!会把 name 当作命令

# 使用变量
echo $name
echo ${name}_server          # 用花括号明确边界

# 变量类型
local_var="local"            # 局部变量(仅当前 Shell)
export GLOBAL_VAR="global"   # 环境变量(子进程可见)
readonly CONST="immutable"   # 只读变量

# 特殊变量
$0              # 脚本名称
$1 $2 $3        # 第1、2、3个参数
$#              # 参数个数
$@              # 所有参数(各自独立)
$*              # 所有参数(作为一个字符串)
$?              # 上一条命令的退出状态码
$$              # 当前 Shell 的 PID
$!              # 最后一个后台进程的 PID
易错点 · 变量定义空格
# 正确
name="Ginc"

# 错误(会尝试执行 name 命令)
name = "Ginc"       # bash: name: command not found

6.3 引号的区别

name="World"

echo "Hello, $name"      # Hello, World   ← 双引号:变量展开
echo 'Hello, $name'      # Hello, $name   ← 单引号:原样输出
echo Hello, \$name         # Hello, $name   ← 反斜杠:转义单个字符

# 命令替换
echo "Today is $(date +%Y-%m-%d)"   # 反引号 `` 也可,但 $() 更推荐
echo "Files: `ls | wc -l`"          # 反引号(不推荐嵌套)
07

重定向与管道

7.1 标准流

文件描述符名称缩写默认设备
0标准输入 stdin<键盘
1标准输出 stdout>屏幕
2标准错误 stderr2>屏幕

7.2 重定向

# 输出重定向
echo "hello" > file.txt          # 覆盖写入
echo "world" >> file.txt         # 追加写入
command 2> error.log              # 重定向错误
command > out.log 2>&1            # 合并 stdout 和 stderr
command &> all.log                 # 同上(Bash 简写)
command > /dev/null 2>&1          # 丢弃所有输出

# 输入重定向
mysql -u root < database.sql      # 从文件读取输入

# Here Document
cat <<EOF > config.txt
server=192.168.1.1
port=8080
EOF

# Here String
grep "error" <<< "this is an error message"
难点 · 2>&1 的顺序
# 正确:先把 stderr 指向 stdout 的位置,再把 stdout 写入文件
command > file.log 2>&1

# 错误:此时 stderr 指向屏幕,后面再重定向 stdout 不影响 stderr
command 2>&1 > file.log           # stderr 仍在屏幕!

记住:重定向从左到右依次执行2>&1 放在 > file 之前时,1 还指向屏幕,所以 stderr 也指向屏幕。

7.3 管道与 xargs

# 管道:前一个命令的 stdout 作为后一个命令的 stdin
cat access.log | grep "404" | wc -l

# 管道不传递 stderr
ls /nonexist | cat                 # cat 不会收到错误信息
ls /nonexist 2>&1 | cat            # 先合并再管道

# xargs — 将 stdin 转为命令参数
find . -name "*.log" | xargs rm              # 删除找到的文件
find . -name "*.log" | xargs -I {} mv {} /backup/  # 占位符
cat urls.txt | xargs -P 4 -I {} curl -sO {}  # 4并发下载
易错点 · 文件名带空格
# find + xargs 遇到空格文件名会出错
find . -name "*.txt" | xargs rm    # "my file.txt" 会拆成两个参数

# 安全写法
find . -name "*.txt" -print0 | xargs -0 rm   # 用 null 分隔
08

文本处理三剑客

8.1 grep — 搜索

grep "error" logfile.txt              # 搜索含 error 的行
grep -i "error" logfile.txt            # 忽略大小写
grep -r "TODO" /project/               # 递归搜索目录
grep -n "error" logfile.txt            # 显示行号
grep -c "error" logfile.txt            # 统计匹配行数
grep -v "debug" logfile.txt            # 反向匹配(排除)
grep -w "error" logfile.txt            # 全词匹配
grep -E "error|warn" logfile.txt       # 扩展正则(egrep)
grep -A 3 "error" logfile.txt          # 匹配行后3行
grep -B 2 "error" logfile.txt          # 匹配行前2行
grep -C 2 "error" logfile.txt          # 匹配行前后各2行
grep --include="*.py" -r "import" .    # 只搜索 .py 文件

8.2 sed — 流编辑器

# 替换
sed 's/old/new/' file.txt              # 替换每行第一个
sed 's/old/new/g' file.txt             # 替换所有(g=全局)
sed -i 's/old/new/g' file.txt          # 原地修改(-i 直接改文件)
sed -i.bak 's/old/new/g' file.txt      # 原地修改并备份为 .bak

# 删除
sed '3d' file.txt                       # 删除第3行
sed '/pattern/d' file.txt               # 删除匹配行
sed '/^$/d' file.txt                    # 删除空行

# 插入/追加
sed '2i\新行内容' file.txt              # 第2行前插入
sed '2a\新行内容' file.txt              # 第2行后追加

# 提取
sed -n '10,20p' file.txt               # 打印第10~20行
sed -n '/start/,/end/p' file.txt       # 打印 start 到 end 之间的内容

# 多个操作
sed -e 's/foo/bar/g' -e 's/baz/qux/g' file.txt

8.3 awk — 文本分析

# 基本语法: awk 'pattern { action }' file

# 打印特定列(默认空格/Tab分隔)
awk '{print $1, $3}' file.txt          # 第1列和第3列
awk -F: '{print $1}' /etc/passwd       # 指定分隔符为 :

# 条件过滤
awk '$3 > 100 {print $1, $3}' data.txt # 第3列大于100的行
awk '/error/ {print}' logfile.txt       # 包含 error 的行

# 内置变量
awk '{print NR, NF, $0}' file.txt      # 行号, 字段数, 整行
awk 'END {print NR}' file.txt           # 总行数

# 统计求和
awk '{sum += $3} END {print sum}' data.txt  # 第3列求和

# 实战:统计 Nginx 日志每个 IP 的请求数
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20

# 格式化输出
awk '{printf "%-20s %10d\n", $1, $3}' data.txt
知识点 · 其他文本工具
工具用途示例
sort排序sort -t: -k3 -n /etc/passwd 按 UID 排序
uniq去重(需先排序)sort file | uniq -c 统计频次
cut按列截取cut -d: -f1,3 /etc/passwd
tr字符替换echo "ABC" | tr 'A-Z' 'a-z'
tee同时输出到屏幕和文件cmd | tee log.txt
wc计数wc -l file 统计行数
diff比较文件差异diff -u old new
jqJSON 处理cat data.json | jq '.users[].name'
09

Shell 脚本编程

9.1 脚本基础

#!/bin/bash
# ↑ Shebang 行:指定解释器,必须在第一行
# 没有 shebang 时用当前 Shell 执行

# 调试模式
bash -x script.sh                # 打印每条执行的命令
set -x                          # 脚本内开启调试
set -e                          # 遇到错误立即退出
set -u                          # 使用未定义变量时报错
set -euo pipefail               # 推荐组合:严格模式

9.2 条件判断

# if 语法
if [ "$a" -eq "$b" ]; then
    echo "相等"
elif [ "$a" -gt "$b" ]; then
    echo "$a 更大"
else
    echo "$b 更大"
fi

# 数值比较
-eq    # 等于       -ne  不等于
-gt    # 大于       -lt  小于
-ge    # 大于等于   -le  小于等于

# 字符串比较
=      # 等于       !=  不等于
-z     # 为空       -n  非空

# 文件测试
-f file    # 是否为文件
-d dir     # 是否为目录
-e path    # 是否存在
-r file    # 是否可读
-w file    # 是否可写
-x file    # 是否可执行
-s file    # 是否非空
file1 -nt file2  # file1 是否比 file2 新

# [[ ]] 是增强版(Bash 推荐)
if [[ "$str" =~ ^[0-9]+$ ]]; then
    echo "是数字"            # 支持正则匹配
fi

# 逻辑组合
if [ "$a" -gt 0 ] && [ "$a" -lt 100 ]; then ...
if [[ "$a" > 0 && "$a" < 100 ]]; then ...
易错点 · [ ] 中的空格
# 正确(方括号内侧必须有空格)
if [ "$a" -eq "$b" ]; then

# 错误(各种空格问题)
if ["$a"-eq"$b"];       # 语法错误
if [ $a -eq $b ]          # 变量为空时会崩溃!

# 最佳实践:始终双引号引用变量
if [ "$a" -eq "$b" ]       # ✓ 安全

9.3 循环

# for 循环
for i in 1 2 3 4 5; do
    echo "$i"
done

for i in {1..100}; do echo "$i"; done

for file in *.log; do
    echo "Processing $file"
done

for ((i=0; i<10; i++)); do
    echo "$i"
done

# while 循环
while IFS= read -r line; do
    echo "$line"
done < file.txt

# 逐行读取文件(推荐上面的方式,保留空格和反斜杠)
while IFS= read -r line; do
    echo "Line: $line"
done < /etc/passwd

9.4 函数

# 定义函数
greet() {
    local name="$1"         # local 声明局部变量
    local greeting="${2:-Hello}"  # 参数默认值
    echo "$greeting, $name!"
    return 0               # 返回状态码(不是值!)
}

greet "Ginc"               # Hello, Ginc!
greet "Bob" "Hi"            # Hi, Bob!

# 函数返回值只能通过 echo + 命令替换获取
add() {
    echo $(( $1 + $2 ))     # 输出结果
}
result=$(add 3 5)            # 捕获输出
echo "$result"               # 8
10

进程管理

10.1 查看进程

ps aux                            # 所有进程(BSD 风格)
ps -ef                            # 所有进程(System V 风格)
ps aux | grep nginx               # 查找特定进程
ps -eo pid,ppid,user,%cpu,%mem,cmd --sort=-%cpu | head -20  # CPU Top 20

top                               # 实时进程监控
htop                              # 增强版 top(需安装)
pstree                            # 进程树
pstree -p                         # 带 PID 的进程树

10.2 进程控制

command &                         # 后台运行
nohup command &                   # 后台运行,不受终端关闭影响
jobs                              # 查看后台任务
fg %1                             # 切到前台
bg %1                             # 继续后台运行

# 发送信号
kill PID                          # 发送 SIGTERM (15) — 优雅终止
kill -9 PID                       # 发送 SIGKILL (9) — 强制终止
kill -HUP PID                     # 发送 SIGHUP (1) — 重新加载配置
killall nginx                     # 按进程名杀死
pkill -f "python app.py"          # 按模式匹配杀死
常用信号
信号编号作用
SIGHUP1挂起 / 重载配置
SIGINT2中断(Ctrl+C)
SIGQUIT3退出并 dump core
SIGKILL9强制终止(不可捕获)
SIGTERM15优雅终止(默认)
SIGSTOP19暂停(不可捕获)
SIGCONT18继续

10.3 前后台管理

# disown — 从 Shell 的作业表中移除(关闭终端不会终止)
long_running_command &
disown

# screen / tmux — 终端复用器(推荐)
tmux new -s mysession             # 新建会话
tmux attach -t mysession          # 重新连接
tmux ls                           # 列出会话
# Ctrl+B, D → 分离会话
11

系统服务 systemd

11.1 systemctl 命令

# 服务管理
systemctl start nginx             # 启动
systemctl stop nginx              # 停止
systemctl restart nginx           # 重启
systemctl reload nginx            # 重载配置(不中断服务)
systemctl status nginx            # 查看状态
systemctl enable nginx            # 开机自启
systemctl disable nginx           # 取消开机自启
systemctl is-active nginx         # 是否运行中
systemctl is-enabled nginx        # 是否开机自启
systemctl mask nginx              # 彻底禁用(连手动都不行)
systemctl unmask nginx            # 取消禁用

# 查看所有服务
systemctl list-units --type=service             # 运行中的
systemctl list-units --type=service --all       # 所有(含未运行)
systemctl list-unit-files --type=service        # 所有服务文件

# 系统操作
systemctl reboot                  # 重启
systemctl poweroff                # 关机

11.2 编写 Unit 文件

# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network.target postgresql.service
Requires=postgresql.service

[Service]
Type=simple
User=appuser
Group=appgroup
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/server --config /etc/myapp/config.yaml
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
EnvironmentFile=-/etc/myapp/env

[Install]
WantedBy=multi-user.target
# 生效步骤
systemctl daemon-reload           # 重新加载 unit 文件
systemctl enable --now myapp      # 启用并立即启动
journalctl -u myapp -f            # 查看日志
知识点 · Service Type
Type含义
simple默认,主进程就是服务进程
forkingfork 到后台运行(需配合 PIDFile)
oneshot一次性任务,执行完退出
notify类似 simple,但会通知 systemd 就绪
12

磁盘与存储

12.1 磁盘查看

lsblk                             # 块设备列表(树形)
lsblk -f                          # 含文件系统和UUID
fdisk -l                          # 分区表详情
blkid                             # 所有块设备的 UUID 和类型
df -h                             # 磁盘使用量(人类可读)
df -i                             # inode 使用量
du -sh /var/log/                  # 目录大小
du -sh /var/log/* | sort -rh | head -10  # 找大目录

12.2 分区与格式化

# 分区(交互式)
fdisk /dev/sdb                    # MBR 分区
gdisk /dev/sdb                    # GPT 分区
parted /dev/sdb                   # 通用分区工具

# 格式化
mkfs.ext4 /dev/sdb1               # 格式化为 ext4
mkfs.xfs /dev/sdb1                # 格式化为 xfs

# 挂载
mount /dev/sdb1 /mnt/data         # 临时挂载
umount /mnt/data                  # 卸载
mount -o ro /dev/sdb1 /mnt/data   # 只读挂载

# 永久挂载 /etc/fstab
# UUID=xxx  /mnt/data  ext4  defaults  0  2

# /etc/fstab 格式
# 设备  挂载点  文件系统  选项  dump  fsck顺序
易错点 · /etc/fstab 错误导致无法启动

修改 fstab 后务必执行 mount -a 测试。fstab 中的错误会导致系统无法启动。建议用 UUID 而非设备名(/dev/sdb1 可能在重启后变化)。

# 查看 UUID
blkid /dev/sdb1

# /etc/fstab 推荐写法
UUID=xxxx-xxxx  /mnt/data  ext4  defaults,noatime  0  2
13

内存与性能

13.1 内存查看

free -h                           # 内存使用情况
cat /proc/meminfo                 # 详细内存信息

# free -h 输出解读:
#               total    used    free   shared  buff/cache  available
# Mem:           15Gi    5.2Gi  1.0Gi   256Mi     9.1Gi      9.5Gi
# ↑ 重点关注 available 而非 free!
# buff/cache 是缓存,可被回收
易错点 · free 中的 "空闲内存"

free 列很少不代表内存不足。Linux 会积极使用空闲内存做磁盘缓存(buff/cache)available 列才是实际可用内存。缓存可以随时被回收,不影响应用。

13.2 性能监控工具

工具用途
top / htop实时 CPU/内存监控
vmstat 1CPU、内存、IO、上下文切换
iostat -xz 1磁盘 IO 详情
sar历史性能数据
iotop进程级 IO 监控
nmon综合性能监控
strace系统调用追踪
lsof打开的文件/连接

13.3 交换空间 (Swap)

# 查看 swap
swapon --show
free -h

# 创建 swap 文件
fallocate -l 2G /swapfile         # 分配 2G
chmod 600 /swapfile               # 修改权限
mkswap /swapfile                  # 格式化
swapon /swapfile                  # 启用

# 永久生效(添加到 /etc/fstab)
# /swapfile  none  swap  sw  0  0

# 调整 swappiness(0~100,越低越不倾向用 swap)
sysctl vm.swappiness=10
# 永久:写入 /etc/sysctl.d/99-swap.conf
14

定时任务 cron

14.1 crontab 语法

# 编辑当前用户的 cron
crontab -e

# 查看
crontab -l

# cron 表达式格式
# ┌───────── 分钟 (0-59)
# │ ┌─────── 小时 (0-23)
# │ │ ┌───── 日 (1-31)
# │ │ │ ┌─── 月 (1-12)
# │ │ │ │ ┌─ 星期 (0-7, 0和7都是周日)
# │ │ │ │ │
# * * * * * command

# 示例
0 2 * * *     /backup.sh          # 每天凌晨2点
*/5 * * * *   /check.sh           # 每5分钟
0 9 * * 1     /weekly.sh          # 每周一9点
0 0 1 * *     /monthly.sh         # 每月1号0点
30 18 * * 1-5 /workday.sh         # 工作日18:30

# 特殊字符串
@reboot    /startup.sh              # 开机时
@daily     /daily.sh                # 等同于 0 0 * * *
@hourly    /hourly.sh               # 等同于 0 * * * *
易错点 · cron 环境变量

cron 的环境变量极简(PATH 可能只有 /usr/bin:/bin),脚本中必须使用绝对路径,否则命令找不到。

# 错误
0 2 * * * backup.sh

# 正确
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

# 或者在 crontab 顶部设置 PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
15

网络管理

15.1 网络配置

# 查看网络
ip addr                           # IP 地址(推荐)
ip route                          # 路由表
ip link                           # 网卡状态
ifconfig                          # 旧命令(已弃用)
ss -tulnp                         # 监听端口(推荐)
netstat -tulnp                    # 监听端口(旧)
cat /etc/resolv.conf              # DNS 配置
hostname -I                       # 本机 IP

# 网络配置文件
# CentOS/RHEL: /etc/sysconfig/network-scripts/ifcfg-eth0
# Ubuntu/Debian: /etc/netplan/*.yaml (Netplan)
#                /etc/network/interfaces (旧版)

15.2 网络诊断

ping -c 4 google.com              # 测试连通性
traceroute google.com             # 路由追踪
mtr google.com                    # 实时路由追踪(ping + traceroute)
nslookup example.com              # DNS 查询
dig example.com                   # DNS 详细查询(推荐)
dig +short example.com            # 简短输出
dig @8.8.8.8 example.com          # 指定 DNS 服务器

# 连通性测试
curl -I https://example.com       # HTTP 头部
curl -v https://example.com       # 详细连接信息
wget https://example.com/file     # 下载文件

# 端口测试
nc -zv host 80                    # 测试端口连通性
nc -zv host 22 80 443             # 测试多个端口
telnet host 80                    # 交互式连接

15.3 防火墙 (firewalld)

# firewalld (CentOS 7+)
firewall-cmd --state                          # 查看状态
firewall-cmd --list-all                       # 列出规则
firewall-cmd --add-service=http --permanent   # 开放 HTTP
firewall-cmd --add-port=8080/tcp --permanent  # 开放端口
firewall-cmd --reload                         # 重载规则

# iptables (更底层)
iptables -L -n                                # 查看规则
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # 允许 SSH
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # 允许 HTTP
iptables -A INPUT -j DROP                     # 拒绝其他
iptables-save > /etc/iptables.rules           # 保存规则
16

SSH 远程管理

16.1 SSH 基础

ssh user@host                     # 连接远程主机
ssh -p 2222 user@host             # 指定端口
ssh user@host "ls -la /var/log"   # 执行远程命令

# 文件传输
scp file.txt user@host:/path/     # 上传
scp user@host:/path/file.txt .    # 下载
scp -r dir/ user@host:/path/      # 递归传输目录
rsync -avz -e ssh src/ user@host:/dest/  # 增量同步(推荐)

16.2 SSH 密钥认证

# 生成密钥对
ssh-keygen -t ed25519 -C "your@email.com"
# 生成在 ~/.ssh/id_ed25519 (私钥) 和 ~/.ssh/id_ed25519.pub (公钥)

# 上传公钥到服务器
ssh-copy-id user@host

# 配置免密登录 ~/.ssh/config
Host myserver
    HostName 192.168.1.100
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

# 然后直接:ssh myserver
安全要点
  • 私钥权限必须是 600chmod 600 ~/.ssh/id_ed25519
  • .ssh 目录权限必须是 700chmod 700 ~/.ssh
  • 生产环境应禁用密码登录PasswordAuthentication no
  • 修改默认端口 22 为其他端口可减少扫描攻击
  • 推荐使用 ed25519 密钥(比 RSA 更安全更短)

16.3 SSH 隧道

# 本地端口转发(访问本地 8080 → 远程 80)
ssh -L 8080:localhost:80 user@host

# 远程端口转发(远程 9090 → 本地 3000)
ssh -R 9090:localhost:3000 user@host

# 动态端口转发(SOCKS 代理)
ssh -D 1080 user@host

# 跳板机(ProxyJump)
ssh -J jumpuser@jumphost admin@target
17

防火墙与安全

17.1 安全加固清单

# 1. 禁用 root SSH 登录
# /etc/ssh/sshd_config
PermitRootLogin no

# 2. 仅允许密钥认证
PasswordAuthentication no

# 3. 安装 fail2ban(防暴力破解)
apt install fail2ban              # Debian/Ubuntu
yum install fail2ban              # CentOS
systemctl enable fail2ban

# 4. 定期更新系统
apt update && apt upgrade         # Debian/Ubuntu
yum update                        # CentOS

# 5. 最小权限原则
# 不用 root 运行应用,创建专用用户

# 6. 关闭不需要的服务
systemctl disable --now telnet
systemctl disable --now ftp

17.2 SELinux / AppArmor

# SELinux (CentOS/RHEL)
getenforce                        # 查看模式: Enforcing/Permissive/Disabled
setenforce 0                      # 临时切换为 Permissive
semanage port -l | grep http      # 查看端口标签
restorecon -Rv /var/www/          # 恢复文件安全上下文

# AppArmor (Ubuntu/Debian)
aa-status                         # 查看状态
aa-enforce /etc/apparmor.d/profile  # 启用配置
难点 · SELinux 导致服务异常

很多运维新手遇到"配置正确但服务不工作"的问题,往往是因为 SELinux 阻止了访问。快速排查:

# 检查 SELinux 是否阻止
ausearch -m avc -ts recent
cat /var/log/audit/audit.log | grep denied

# 如果确认是 SELinux,正确做法是添加策略,而非直接禁用
setsebool -P httpd_can_network_connect on
18

日志管理

18.1 重要日志文件

日志文件内容
/var/log/syslog系统日志(Debian/Ubuntu)
/var/log/messages系统日志(CentOS/RHEL)
/var/log/auth.log认证日志(Debian/Ubuntu)
/var/log/secure认证日志(CentOS/RHEL)
/var/log/kern.log内核日志
/var/log/dmesg硬件/驱动日志
/var/log/nginx/Nginx 日志
/var/log/cron定时任务日志

18.2 journalctl (systemd)

journalctl -xe                    # 最近日志(含解释)
journalctl -u nginx               # 指定服务的日志
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx --since "2024-01-15" --until "2024-01-16"
journalctl -f                     # 实时跟踪(类似 tail -f)
journalctl -p err                 # 只看错误级别
journalctl --disk-usage           # 日志占用空间
journalctl --vacuum-size=500M     # 清理到 500M

18.3 logrotate

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily                   # 每天轮转
    missingok               # 文件不存在不报错
    rotate 30               # 保留30份
    compress                # gzip 压缩
    delaycompress           # 延迟一次压缩
    notifempty              # 空文件不轮转
    create 644 root root    # 新文件权限
    postrotate
        systemctl reload myapp
    endscript
}

# 手动测试
logrotate -d /etc/logrotate.d/myapp   # 调试模式
logrotate -f /etc/logrotate.d/myapp   # 强制执行
19

包管理

19.1 Debian/Ubuntu (apt)

apt update                        # 更新包索引(必须先执行!)
apt upgrade                       # 升级所有包
apt install nginx                 # 安装
apt remove nginx                  # 删除(保留配置)
apt purge nginx                   # 完全删除(含配置)
apt autoremove                    # 清理不需要的依赖
apt search nginx                  # 搜索
apt show nginx                    # 包信息
apt list --installed              # 已安装的包
dpkg -l                           # 已安装的包(底层)
dpkg -L nginx                     # 包含的文件
dpkg -S /usr/bin/nginx            # 属于哪个包

19.2 RHEL/CentOS (yum/dnf)

yum update                        # 更新
yum install nginx                 # 安装
yum remove nginx                  # 删除
yum search nginx                  # 搜索
yum info nginx                    # 信息
yum list installed                # 已安装
yum provides /usr/bin/nginx       # 查找文件所属包
yum history                       # 操作历史
yum history undo 42               # 撤销第42次操作

# CentOS 8+ / Fedora 用 dnf 替代 yum
dnf install nginx
20

LVM 与 RAID

20.1 LVM(逻辑卷管理)

# LVM 层次:物理卷(PV) → 卷组(VG) → 逻辑卷(LV)

# 创建
pvcreate /dev/sdb /dev/sdc         # 创建物理卷
vgcreate data_vg /dev/sdb /dev/sdc # 创建卷组
lvcreate -L 50G -n app_lv data_vg  # 创建逻辑卷(固定大小)
lvcreate -l 100%FREE -n app_lv data_vg  # 使用所有空间

# 格式化和挂载
mkfs.ext4 /dev/data_vg/app_lv
mount /dev/data_vg/app_lv /app

# 扩容(LVM 最大优势!)
lvextend -L +20G /dev/data_vg/app_lv    # 扩大 20G
resize2fs /dev/data_vg/app_lv            # ext4 扩容文件系统
xfs_growfs /app                           # xfs 扩容文件系统

# 查看
pvdisplay, vgdisplay, lvdisplay
pvs, vgs, lvs                     # 简洁视图
知识点 · LVM 快照
# 创建快照(用于备份,几乎瞬间完成)
lvcreate -L 5G -s -n app_snap /dev/data_vg/app_lv
mount /dev/data_vg/app_snap /mnt/snapshot
# 备份完成后删除快照
lvremove /dev/data_vg/app_snap
21

内核与模块

21.1 内核参数调优

# 查看内核参数
sysctl -a                         # 所有参数
sysctl net.ipv4.ip_forward        # 查看单个参数

# 临时修改
sysctl -w net.ipv4.ip_forward=1

# 永久修改 → /etc/sysctl.d/99-custom.conf
net.ipv4.ip_forward = 1
net.core.somaxconn = 65535
vm.swappiness = 10
fs.file-max = 655350

# 使配置生效
sysctl --system                   # 加载所有配置文件

# 查看内核版本
uname -r                         # 内核版本
uname -a                         # 全部信息

21.2 内核模块

lsmod                             # 已加载模块
modprobe module_name              # 加载模块
modprobe -r module_name           # 卸载模块
modinfo module_name               # 模块信息
22

Docker 容器

22.1 Docker 基础命令

# 镜像操作
docker pull nginx:1.24            # 拉取镜像
docker images                     # 列出镜像
docker rmi nginx:1.24             # 删除镜像
docker image prune                # 清理无用镜像

# 容器操作
docker run -d -p 80:80 --name web nginx   # 后台运行,映射端口
docker run -it ubuntu bash        # 交互式运行
docker ps                         # 运行中的容器
docker ps -a                      # 所有容器(含停止的)
docker stop web                   # 停止
docker start web                  # 启动
docker restart web                # 重启
docker rm web                     # 删除容器
docker exec -it web bash          # 进入容器
docker logs -f web                # 查看日志
docker inspect web                # 详细信息
docker stats                      # 资源监控

# 清理
docker system prune -a            # 清理所有无用资源

22.2 Dockerfile

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]

# 构建
docker build -t myapp:latest .

# Docker Compose
docker compose up -d              # 后台启动所有服务
docker compose down               # 停止并删除
docker compose logs -f            # 查看日志
23

故障排查

23.1 系统排查流程

# 1. 系统整体状态
uptime                            # 负载均值(1/5/15分钟)
                                  # 理想值 < CPU 核数
free -h                           # 内存
df -h                             # 磁盘
iostat -xz 1                      # IO

# 2. CPU 排查
top -c                            # 按 CPU 排序,找高消耗进程
pidstat -u 1                      # 每秒进程 CPU
perf top                          # CPU 热点函数

# 3. 内存排查
ps aux --sort=-%mem | head -20    # 内存 Top 20
slabtop                           # 内核 slab 缓存
cat /proc/meminfo                 # 详细内存信息

# 4. 磁盘排查
iotop                             # IO Top
lsof +D /var/log/                 # 谁在用这个目录
fuser -v /mnt/data                # 谁在用这个挂载点

# 5. 网络排查
ss -s                             # 连接统计
ss -tnp                           # TCP 连接详情
tcpdump -i eth0 port 80           # 抓包

23.2 常见问题速查

症状排查命令常见原因
系统很卡top, vmstat 1CPU 满载、内存不足、IO 瓶颈
磁盘满df -h, du -sh /*日志爆满、大文件、inode 耗尽
服务无法启动systemctl status, journalctl -xe配置错误、端口占用、权限
无法远程连接ss -tlnp, iptables -L防火墙、SSH 配置、网络不通
OOM Killeddmesg | grep oom内存不足被内核杀死
僵尸进程ps aux | grep Z父进程未回收子进程

23.3 strace 系统调用追踪

# 追踪命令的系统调用
strace ls /tmp                    # 追踪 ls 命令
strace -p 1234                    # 追踪运行中的进程
strace -e open,read -p 1234       # 只追踪 open 和 read
strace -c ls /tmp                 # 统计系统调用
strace -f -p 1234                 # 追踪子进程
24

易错点速查表

命令行陷阱

#易错点正确做法
1rm -rf /rm -rf ~永远不要执行;用 trash-put
2chmod 777 生产目录最小权限原则:755 / 644
3usermod -G 覆盖附加组必须用 usermod -aG
4变量赋值有空格 a = 1a=1(无空格)
5[ $a = $b ] 变量为空[ "$a" = "$b" ](双引号)
62>&1 顺序错误cmd > file 2>&1(在后面)
7fstab 写错无法启动修改后 mount -a 测试
8cron 里用相对路径全部用绝对路径
9free 的 free 列available
10kill -9 作为首选kill(SIGTERM),不行再 -9
11ifconfigip addr(ifconfig 已弃用)
12sed -i 无备份sed -i.bak(先备份)
13find + xargs 文件名有空格-print0 | xargs -0
14SELinux 禁用了事添加正确的 SELinux 策略
15root 运行应用创建专用用户
经典坑 · 磁盘满排查
# 现象:df -h 显示磁盘满,但 du -sh /* 加起来不够
# 原因:已删除文件仍被进程持有(文件句柄未释放)

# 排查
lsof | grep deleted              # 查找已删除但未释放的文件

# 解决:重启占用进程
systemctl restart nginx           # 释放文件句柄

# 不重启释放(不推荐)
echo > /proc/PID/fd/FD_NUMBER    # 清空文件描述符
经典坑 · 端口被占用
# 错误信息:bind: address already in use

# 找到占用端口的进程
ss -tlnp | grep :80
lsof -i :80

# 杀掉进程
kill PID

# 或者允许端口快速复用(开发环境)
sysctl -w net.ipv4.tcp_tw_reuse=1
Linux系统操作黄金法则
  1. 先备份再操作 — 修改配置前 cp file file.bak
  2. 先测试再应用 — 用 mount -anginx -tvisudo -c
  3. 用最小权限 — 不用 root 跑服务,不给 777
  4. 先 kill 再 kill -9 — 给进程优雅退出的机会
  5. 看日志 — 80% 的问题能在日志中找到答案
  6. 用 tmux/screen — 防止 SSH 断开导致操作中断
  7. 自动化 — 能写脚本就不手动操作
  8. 监控先行 — 出问题前就知道