Skip to content

Linux Shell 实战手册 ​

#系统 · #工具 · #Shell · #Bash · #Linux · #命令行

面向后端开发/运维的 Shell 命令速查与深入。以"场景 → 命令 → 示例"组织,覆盖日常开发、调试、性能诊断和网络排障。


1. 文件与目录操作 ​

1.1 ls — 列出目录 ​

bash
ls -l        # 长格式:权限、所有者、大小、时间
ls -lh       # 人类可读大小(1K, 234M, 2G)
ls -la       # 显示所有包括隐藏文件(.开头)
ls -lt       # 按修改时间排序,最新的在前
ls -ltr      # 按时间逆序,最旧的在前面
ls -lS       # 按文件大小排序
ls -R        # 递归列出子目录
ls -i        # 显示 inode 号
ls -Z        # 显示 SELinux 标签

# 按时间列出最近修改的 5 个文件
ls -lt | head -6

# 只显示目录
ls -d */

# 查看目录本身而非内容
ls -ld /some/dir

1.2 find — 文件搜索(最强大) ​

bash
# === 按名称 ===
find . -name "*.go"              # 精确匹配(区分大小写)
find . -iname "*.GO"             # 忽略大小写
find . -name "*.go" -o -name "*.rs"  # -o = OR

# === 按类型 ===
find . -type f          # 普通文件
find . -type d          # 目录
find . -type l          # 符号链接
find . -type s          # socket 文件

# === 按时间 ===
find . -mtime -1        # 最近 24 小时修改过的
find . -mtime +7        # 7 天前修改的
find . -mtime -7 -mtime +1  # 1~7 天前修改
find . -mmin -30        # 最近 30 分钟内修改的
find . -newer file.txt  # 比 file.txt 新的文件

# === 按大小 ===
find . -size +100M      # 大于 100MB
find . -size -10k       # 小于 10KB
find . -size +1G -size -5G  # 1GB~5GB
find . -empty           # 空文件或空目录

# === 按权限/所有者 ===
find . -perm 644        # 权限精确为 644
find . -perm /u+x       # 任何用户有执行权限
find . -user nobody     # 属于 nobody 的文件
find . -nouser          # 所有者不存在的文件(孤儿文件)

# === 组合动作 ===
find . -name "*.tmp" -delete         # 找到并删除
find . -name "*.go" -exec wc -l {} + # 统计行数
find . -name "*.log" -mtime +30 -exec gzip {} \;

# === 排除目录 ===
find . -name "*.go" -not -path "./vendor/*"
find . -name "*.go" -not \( -path "./vendor" -prune \)

# === 深度控制 ===
find . -maxdepth 2 -name "*.go"     # 最多深入 2 层
find . -mindepth 2 -name "*.go"     # 至少 2 层深度

1.3 xargs — 将标准输入转为命令行参数 ​

bash
# 基础:将 find 结果传给命令
find . -name "*.tmp" | xargs rm

# 处理包含空格的文件名(必须!)
find . -name "*.log" -print0 | xargs -0 rm

# 限制每次调用传递的参数个数
find . -name "*.go" | xargs -n 10 gofmt -w      # 每 10 个文件调用一次
cat urls.txt | xargs -n 1 curl -O               # 逐个下载

# 并行执行(多进程)
find . -name "*.png" | xargs -P 8 -n 1 optipng  # 8 个进程并行

# 占位符替换(灵活控制参数位置)
find . -name "*.log" | xargs -I {} mv {} /backup/{}
#   -I {}   → 用 {} 代表每个输入项,可重复使用

1.4 cp / mv / rm ​

bash
# cp
cp -r src dst          # 递归复制目录
cp -p src dst          # 保留权限、时间戳
cp -a src dst          # 归档模式(= -dR --preserve=all),保留所有属性+符号链接
cp -u src dst          # 仅复制更新的文件(update)
cp -v src dst          # 显示过程(verbose)

# mv
mv -i src dst          # 覆盖前确认
mv -n src dst          # 不覆盖已存在的
mv -v src dst          # 显示过程

# rm
rm -rf dir             # 递归强制删除(⚠️ 谨慎使用)
rm -i file             # 删除前确认
rm -v file             # 显示删除过程

# 安全删除技巧:先移动到临时目录再定期清理
mkdir -p /tmp/to_delete
mv old_stuff /tmp/to_delete/   # 观察几天没问题再 rm -rf

1.5 ln — 链接 ​

bash
ln -s /path/to/target link_name     # 软链接(符号链接),可跨文件系统
ln    /path/to/target link_name     # 硬链接,同一文件多名字,不能跨文件系统

# 判断是否是符号链接
ls -l link_name         # 看到 `-> target`
readlink link_name      # 查看指向
readlink -f link_name   # 查看绝对路径目标

# 常见用途
ln -s /usr/local/go/bin/go /usr/local/bin/go   # 添加到 PATH
ln -s /opt/app-v2.1 /opt/app-current           # 版本切换

2. 文本查看与处理 ​

2.1 cat + tac + head + tail ​

bash
# cat(concatenate)
cat file1 file2 > merged             # 合并文件
cat -n file                          # 带行号输出
cat -A file                          # 显示所有不可见字符(^I=Tab, $=换行)
echo "abc" | cat -                   # - 代表 stdin

# tac — 反向输出(最后一行最先)
tac access.log | head -20            # 看最新的 20 条日志

# head — 看头部
head -20 file                        # 前 20 行
head -c 1024 file                    # 前 1024 字节

# tail — 看尾部(最常用于日志)
tail -f access.log                   # 跟踪文件增长(Ctrl+C 退出)
tail -F access.log                   # 同 -f,但文件被删除/轮转后自动重新打开
tail -n 100 access.log               # 最后 100 行
tail -n +100 access.log              # 从第 100 行开始
tail -f access.log | grep "ERROR"    # 实时过滤

2.2 less — 分页查看(比 more 强大百倍) ​

bash
less file                            # 进入浏览模式
# 浏览时常用快捷键:
#   space / f    下一页           b          上一页
#   g            跳到开头          G          跳到末尾
#   /pattern     向下搜索         ?pattern    向上搜索
#   n            下一个匹配        N          上一个匹配
#   -i           忽略大小写搜索    &pattern   只显示匹配行
#   F            进入 tail -f 模式(跟随)
#   v            用 $EDITOR 打开当前文件
#   h            帮助

# 直接搜索
less -p "ERROR" app.log             # 打开并跳到第一个 ERROR

# 管道中使用
ps aux | less                        # 安全浏览长输出
git diff | less -R                   # -R 保留颜色

2.3 wc + sort + uniq ​

bash
# wc(word count)
wc -l file          # 行数(最常用)
wc -w file          # 单词数
wc -c file          # 字节数
wc -m file          # 字符数(处理多字节字符如中文时用 -m)
find . -name "*.go" | xargs wc -l   # 统计总代码行数

# sort
sort -n file        # 按数值排序
sort -r file        # 逆序
sort -h file        # 人类可读大小(1K, 1G)
sort -u file        # 去重(unique)
sort -t ':' -k2 file     # -t 分隔符, -k 按第 n 列
sort -t ',' -k2,2nr file  # 按第 2 列数值逆序

# uniq — 报告或删除相邻重复行(通常与 sort 配合)
sort file | uniq            # 去重
sort file | uniq -c         # 统计出现次数(最常用)
sort file | uniq -d         # 只显示重复行
sort file | uniq -u         # 只显示不重复行

# 实战:统计 access.log 中访问最多的 10 个 IP
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10

2.4 cut + tr + diff ​

bash
# cut — 按列提取
cut -d ':' -f 1 /etc/passwd          # 提取第 1 列
cut -d ',' -f 1,3 data.csv           # 提取第 1、3 列
cut -c 1-10 file                     # 提取每行第 1~10 个字符
echo "/a/b/c" | cut -d '/' -f 2-     # 去掉第一个分隔符前面的内容

# tr — 字符替换/删除
echo "HELLO" | tr 'A-Z' 'a-z'       # 大小写转换
echo "a  b   c" | tr -s ' '          # 压缩连续空格
cat file | tr -d '\r'                # 删除 Windows 换行符 CR(\\r)
cat file | tr -cd '[:print:]\n'      # 删除所有不可打印字符

# diff — 差异对比
diff file1 file2                     # 基础对比
diff -u file1 file2                  # 统一格式(最常用,像 git diff)
diff -r dir1 dir2                    # 递归对比目录
diff -y file1 file2                  # 并排显示
diff -q file1 file2                  # 只报告是否不同

# comm — 按行比较两个已排序文件
comm file1 file2                     # 3列: 只在1的 / 只在2的 / 公共的
comm -12 file1 file2                 # 只显示公共行(取交集)
comm -23 file1 file2                 # 只在 file1 中的行

2.5 tee — 分流输出(同时写文件和 stdout) ​

bash
# 把输出同时写到文件和屏幕
./script.sh | tee output.log

# 追加而非覆盖
./script.sh | tee -a output.log

# 同时写到多个文件 + 继续管道
cat access.log | tee copy1.log copy2.log | wc -l

# 常见模式:保存中间结果同时继续处理
curl -s https://api.example.com/data | tee raw.json | jq '.items[]'

3. 文本处理三剑客 ​

3.1 grep — 文本搜索 ​

bash
# === 基础 ===
grep "pattern" file                    # 搜索字符串
grep -i "PATTERN" file                 # 忽略大小写
grep -v "pattern" file                 # 反向:不包含的行
grep -r "pattern" .                    # 递归搜索目录
grep -n "pattern" file                 # 显示行号
grep -c "pattern" file                 # 统计匹配行数
grep -w "word" file                    # 完整单词匹配
grep -l "pattern" *.go                 # 只显示包含匹配的文件名
grep -L "pattern" *.go                 # 只显示不包含匹配的文件名

# === 上下文 ===
grep -A 3 "ERROR" app.log             # 匹配行 + 后 3 行 (After)
grep -B 3 "ERROR" app.log             # 匹配行 + 前 3 行 (Before)
grep -C 3 "ERROR" app.log             # 匹配行 + 前后各 3 行 (Context)

# === 高级 ===
grep -E "err|fail|panic" app.log      # 正则(等同于 egrep)
grep -P "\\d{4}-\\d{2}-\\d{2}" file   # Perl 正则(更强)⚠️ macOS 不支持 -P
grep -o "\\d+\\.\\d+\\.\\d+\\.\\d+" file  # 只输出匹配部分(-o)
grep -H "pattern" *                    # 多文件时强制显示文件名
grep -A 20 "panic" app.log | tail -n +15  # 取匹配后第15~20行

# === 二进制文件 ===
grep -a "string" binary_file           # 把二进制当文本处理

# === 实战场景 ===
# 场景1: 大日志文件快速搜索(LC_ALL=C 加速 10×+)
LC_ALL=C grep "ERROR" huge.log         # 跳过 UTF-8 验证,大幅提速

# 场景2: 从文件读取匹配模式
grep -f blacklist.txt access.log       # 匹配黑名单中任意 IP/UA

# 场景3: 匹配但排除某些模式
grep "ERROR" app.log | grep -v "known_bug\|TEST"  # 排除噪音

# 场景4: 只输出文件名+匹配内容(适合 IDE 跳转格式)
grep -rn "TODO" --include="*.go" .     # 输出: path/file.go:42: // TODO: fix

# 场景5: 统计各模块错误分布
grep -r "ERROR" --include="*.log" . | awk -F: '{print $1}' | sort | uniq -c | sort -rn

# 场景6: 快速确认代码中是否引入了危险函数
grep -rnE "(strcpy|gets|sprintf)\s*\(" --include="*.c" .   # C 不安全函数
grep -rnE "(eval|exec|system)\s*\(" --include="*.py" .     # Python 危险调用

# 场景7: 搜索 zip/jar 等归档中的文本(zgrep)
zgrep "pattern" archive.gz             # 不解压直接搜索 gzip 文件
zipgrep "pattern" archive.zip          # 不解压搜索 zip

3.2 sed — 流编辑器 ​

bash
# === 替换(s 命令)===
sed 's/old/new/' file                  # 每行只替换第一个
sed 's/old/new/g' file                 # 每行替换所有 (g=global)
sed 's/old/new/2' file                 # 每行只替换第 2 个
sed 's/old/new/gi' file                # 忽略大小写 + 全局
sed 's|/path/to/old|/new/path|g' file  # 用 | 做分隔符避免转义 /

# === 地址范围(指定行)===
sed '5s/old/new/' file                 # 只改第 5 行
sed '5,10s/old/new/g' file             # 5~10 行
sed '/start/,/end/s/old/new/g' file    # 匹配 start 到 end 区域
sed '/pattern/!s/old/new/g' file       # ! = 不匹配的行才替换

# === 删除/打印 ===
sed '5d' file                          # 删除第 5 行
sed '5,10d' file                       # 删除 5~10 行
sed '/^$/d' file                       # 删除空行
sed '/^#/d' file                       # 删除注释行(#开头)
sed -n '5p' file                       # 只打印第 5 行
sed -n '/pattern/p' file               # 只打印匹配行(= grep)

# === 插入/追加 ===
sed '1i\\HEADER' file                  # 第 1 行前插入
sed '$a\\FOOTER' file                  # 最后一行后追加 ($ = 最后一行)
sed '/pattern/a\\NEW LINE' file        # 匹配行后追加

# === 实战 ===
# 删除行首空白
sed 's/^[[:space:]]*//' file
# 删除行尾空白
sed 's/[[:space:]]*$//' file
# 删除 C/C++ 注释
sed 's|//.*||' file
# 提取引号内内容
echo 'foo="bar"' | sed 's/.*"\(.*\)".*/\\1/'

# 原地修改(macOS 注意事项)
sed -i 's/old/new/g' file              # Linux
sed -i '' 's/old/new/g' file           # macOS(需要空 backup 后缀)

# === 多行处理 ===
sed 'N;s/\n/ /' file                   # N=读入下一行, 合并两行为一行
sed '/pattern/{N;s/\n/---/}' file      # 匹配行后将下一行用 --- 连接
sed -n '/start/,/end/p' file           # 打印两个模式之间的所有行(含边界)

# === hold space(高级缓存区)===
# h/H = copy/append pattern space → hold space
# g/G = copy/append hold space → pattern space
# x = 交换 hold space 和 pattern space
sed -n '1h;1!H;${g;s/\n/,/g;p}' file   # 将所有行用逗号连接成一行

# === 条件分支 ===
sed '/^#/b; s/foo/bar/' file           # 跳过注释行,其余行替换
sed 's/\([0-9]\{3\}\)\([0-9]\{3\}\)\([0-9]\{4\}\)/(\1) \2-\3/'  # 电话号码格式化

# === 更多实战场景 ===
# 场景1: 提取 XML/HTML 标签内容
echo '<title>Hello World</title>' | sed 's/<[^>]*>//g'

# 场景2: 删除行尾回车符(DOS → Unix)
sed -i 's/\r$//' *.txt

# 场景3: 在第 N 行后插入多行
sed '3a\line1\nline2\nline3' file

# 场景4: YAML 缩进调整(4空格 → 2空格)
sed 's/^\( \+\)/\1\1/;s/^    /  /' config.yml

# 场景5: 生成 SQL INSERT 语句
sed "s/.*/INSERT INTO t VALUES ('&');/" names.txt

# 场景6: 打印两个模式之间的行(不含边界)
sed -n '/START/,/END/{/START/b;/END/b;p}' file

3.3 awk — 文本处理语言 ​

bash
# === 基础结构 ===
# awk '条件 { 动作 }' file
# 默认分隔符为空白(空格/Tab),自动分割为 $1, $2, $3...

awk '{print $1, $3}' file              # 打印第 1、3 列
awk '{print $NF}' file                 # NF = 最后一列
awk '{print $(NF-1)}' file             # 倒数第 2 列
awk '{print NR": "$0}' file            # NR = 行号, $0 = 整行
awk 'NF > 0' file                      # 只打印非空行

# === 条件过滤 ===
awk '$3 > 100 {print $1, $3}' data.txt
awk '$1 ~ /pattern/ {print $0}' file   # ~ = 正则匹配
awk '$1 !~ /pattern/ {print $0}' file  # !~ = 不匹配
awk '$2 >= 100 && $3 < 200' file       # 多条件

# === 分隔符 ===
awk -F ':' '{print $1}' /etc/passwd    # -F 指定分隔符
awk -F '[,;]' '{print $2}' file        # 多个分隔符(正则字符类)

# === 内建变量 ===
awk '{print NR, NF, $0}' file          # 行号、字段数、整行
awk '{sum += $1} END {print sum}' file # BEGIN/END 块

# === BEGIN / END ===
awk 'BEGIN {FS=":"; OFS=" → "} {print $1, $7} END {print "共", NR, "行"}' /etc/passwd

# === 实战 ===
# 计算某列平均值
awk '{sum+=$2; count++} END {if(count>0) print sum/count}' data.txt

# 按某列分组统计
awk '{count[$1]++; sum[$1]+=$2} END {for (k in count) print k, count[k], sum[k]}' data.txt

# 提取 2 列到 4 列之间的内容
awk 'NR>=2 && NR<=4' file

# 合并多行(例如把每 3 行合并为 1 行)
awk 'ORS=NR%3?" ":"\\n"' file

# 日志分析:统计每小时的请求数
awk '{print substr($4, 2, 14)}' access.log | sort | uniq -c | sort -rn | head

# === 进阶实战场景 ===
# 场景1: CSV 带引号字段解析(FPAT 是 gawk 特有)
awk -v FPAT='[^,]*|"[^"]*"' '{print $2}' data.csv

# 场景2: 两个文件 join(类似 SQL JOIN)
awk 'NR==FNR {map[$1]=$2; next} {print $0, map[$1]}' file1 file2
#   NR==FNR 表示在处理第一个文件

# 场景3: 统计 HTTP 状态码分布(日志分析经典模式)
awk '{status[$9]++} END {for (s in status) printf "HTTP %s: %d (%.1f%%)\n", s, status[s], status[s]*100/NR}' access.log

# 场景4: 按时间窗口聚合(如每 5 分钟统计 QPS)
awk '{ts=substr($4,2,17); min=substr(ts,1,15) int(substr(ts,16,2)/5)*5; cnt[min]++} END {for (t in cnt) print t, cnt[t]/300}' access.log | sort

# 场景5: 读取配置生成 Nginx 配置块
awk '/^server/ {print "upstream backend_" $2 " {"}
     /^  host/ {print "  server " $3 ";"}
     /^  end/ {print "}"}' config.txt

# 场景6: 跨多行日志合并(用空行分隔的事务日志)
awk 'BEGIN {RS=""; FS="\n"} /ERROR/ {print $0 "\n---"}' transaction.log

# 场景7: 处理 syslog 并提取关键字段
awk '{
    match($0, /([0-9]{2}:[0-9]{2}:[0-9]{2}) .*? ([a-zA-Z0-9_-]+)\[([0-9]+)\]: (.*)/, arr);
    print arr[1], arr[2], arr[3], substr(arr[4], 1, 80)
}' /var/log/syslog

# 场景8: 格式化输出表格(printf)
awk 'BEGIN {printf "%-20s %10s %10s\n", "NAME", "COUNT", "PERCENT"}
     {printf "%-20s %10d %9.1f%%\n", $1, $2, $2*100/sum}' sum=1000 data.txt

4. 用户与权限 ​

4.1 chmod / chown / chgrp ​

bash
# chmod — 修改权限
chmod 755 script.sh                     # rwxr-xr-x
chmod u+x script.sh                     # owner +x
chmod go-w file                         # group/other -w
chmod -R 755 dir                        # 递归修改

# 权限数字记忆:
#   r=4, w=2, x=1
#   750 = rwxr-x---  (owner全权, group读执行, other无)
#   644 = rw-r--r--  (owner读写, 其他只读)
#   600 = rw-------  (owner独占)

# chown — 修改所有者
chown user:group file                   # 同时修改 user 和 group
chown -R user dir                       # 递归

# chgrp — 只修改组
chgrp group file

4.2 sudo / su ​

bash
sudo command                            # 以 root 执行一个命令
sudo -i                                 # 获取 root shell(interactive)
sudo -u postgres psql                   # 以其他用户身份执行
sudo !!                                 # !! = 上一条命令(最实用的快捷方式)
sudo -E cmd                             # 保留当前用户环境变量

su - username                           # 切换到 username(- = 加载对方环境)

4.3 umask — 默认权限掩码 ​

bash
umask            # 查看当前值:0022
umask 0027       # 设置:文件默认 640,目录默认 750

# 计算: 文件默认 666 - umask, 目录默认 777 - umask
# umask=022 → 文件 644, 目录 755
# umask=077 → 文件 600, 目录 700(最安全)

5. 进程管理 ​

5.1 ps — 查看进程 ​

bash
ps aux                   # 所有进程,BSD 格式(最常用)
ps -ef                   # 所有进程,Unix 格式
ps -eLf                  # 显示线程(L = 线程视图)
ps aux --sort=-%mem      # 按内存使用排序
ps aux | head -1; ps aux | sort -k3rn | head  # 按 CPU 使用排序

# 字段含义:
#   USER  进程所有者
#   PID   进程 ID
#   %CPU  CPU 使用率
#   %MEM  物理内存使用率
#   VSZ   虚拟内存大小 (KB)
#   RSS   常驻内存大小 (KB)
#   TTY   终端
#   STAT  进程状态 (R=运行, S=睡眠, D=不可中断睡眠, Z=僵尸, T=停止)
#   START 启动时间
#   TIME  累计 CPU 时间
#   COMMAND 命令

ps -o pid,ppid,user,%cpu,%mem,cmd -p $$   # 自定义输出列

5.2 top / htop / atop ​

bash
top                              # 交互式进程监控
# top 界面快捷键:
#   1      显示/隐藏每个 CPU 核心
#   P      按 CPU 排序
#   M      按内存排序
#   c      显示完整命令行
#   k      杀死进程(输入 PID)
#   u      按用户过滤
#   H      显示线程

htop                             # top 增强版(彩色、鼠标、树状视图)
#   需要安装: apt install htop

atop                             # 历史性能记录
#   特点: 后台守护进程记录,支持回溯历史时刻的负载
#   查看: atop -r /var/log/atop/atop_20260711

5.3 kill / killall / pkill ​

bash
# 信号列表
kill -l                       # 查看所有信号
# 常用信号:
#   1  SIGHUP   重新加载配置(不终止进程)
#   2  SIGINT   相当于 Ctrl+C
#   9  SIGKILL  强制杀死(不能被捕获/忽略)
#   15 SIGTERM  优雅终止(默认)
#   17 SIGSTOP  暂停进程(不能被捕获)

kill PID                      # 默认 SIGTERM
kill -9 PID                   # 强制杀死
kill -HUP PID                 # 重新加载配置

killall -9 process_name       # 按名称杀所有
pkill -f "python script.py"   # 按完整命令行匹配
pkill -u username             # 杀某用户的所有进程

# 优雅的重启模式
kill -HUP $(cat /var/run/nginx.pid)

5.4 nohup / disown / & ​

bash
# 后台运行 & 脱离终端
nohup ./long_task.sh &          # nohup 忽略 SIGHUP,输出到 nohup.out
nohup ./task.sh > task.log 2>&1 &

# disown — 将已在运行的作业从 shell 作业列表中移除
./long_task.sh &
disown                          # 移除最近的后台作业

# 查看后台作业
jobs -l

# bg/fg — 暂停/恢复
Ctrl+Z                          # 暂停前台进程
bg %1                           # 在后台继续运行作业 1
fg %1                           # 把作业 1 拉回前台

6. 系统性能诊断 ​

6.1 vmstat — 虚拟内存统计(全景快照) ​

bash
vmstat 1 5            # 每秒输出一次,共 5 次

# 输出解读:
#   procs:
#     r = 运行队列(等待 CPU 的进程数) → 持续 > CPU 核数说明 CPU 瓶颈
#     b = 阻塞进程(等待 IO)
#   memory:
#     swpd  = 使用的 swap (KB)
#     free  = 空闲内存
#     buff  = 缓冲区内存
#     cache = 页缓存
#   swap:
#     si = swap in (从磁盘读入)  → >0 说明内存不足
#     so = swap out (写到磁盘)   → >0 说明内存不足
#   io:
#     bi = 从块设备读入的块
#     bo = 写到块设备的块
#   system:
#     in = 中断次数/s
#     cs = 上下文切换/s  → 过高可能线程/进程过多
#   cpu:
#     us = 用户态 CPU
#     sy = 系统态 CPU
#     id = 空闲
#     wa = 等待 IO → 持续高值说明磁盘瓶颈
#     st = 被 hypervisor 偷走的时间(虚拟机)

6.2 iostat — 磁盘 IO 统计 ​

bash
iostat -x 1 5         # -x 扩展统计, 每秒 1 次, 共 5 次

# 关键字段:
#   r/s, w/s     = 每秒读写次数
#   rKB/s, wKB/s = 每秒读写 KB
#   await        = 平均等待时间 (ms) → 高值说明磁盘慢
#   svctm        = 平均服务时间 (ms)
#   %util        = 设备使用率 → 接近 100% 说明磁盘饱和
#   aqu-sz       = 平均队列长度

iostat -m 1           # 以 MB 为单位显示
iostat -p sda 1       # 只看 sda 磁盘

6.3 free — 内存使用 ​

bash
free -h               # 人类可读

# 输出解读:
#   total  = 总物理内存
#   used   = 已使用(不含 buffer/cache)
#   free   = 完全空闲
#   shared = tmpfs 等共享内存
#   buff/cache = 内核缓冲区+页缓存(可回收)
#   available = 实际可用(≈ free + 可回收的 buff/cache)

# Linux 内存口诀:
#   内存不用白不用 → cached 高是好事,不是问题
#   available 低 + swap 使用 → 内存不足

6.4 strace — 系统调用追踪(终极调试武器) ​

bash
# 追踪新进程
strace ls                       # 基本用法
strace -c ls                    # 汇总统计(-c = count)
strace -e open,read,write ls    # 只看特定系统调用
strace -e trace=file ls         # 只看文件相关调用
strace -e trace=network nc -z google.com 80  # 只看网络调用
strace -f ./program             # -f 追踪子进程
strace -p 12345                 # 附加到运行中的进程
strace -s 1024 -p 12345         # -s 增加字符串显示长度
strace -t -o trace.log ./prog   # -t 时间戳, -o 输出到文件
strace -k ./prog                # 打印调用栈(需要 strace 4.17+)

# 经典场景:
#   程序卡住了?→ strace -p PID 看它在等什么
#   文件找不到?→ strace -e open ./prog 看它打开了哪些路径
#   性能问题?→ strace -c ./prog 找调用次数最多的系统调用

# === 进阶实战场景 ===
# 场景1: 精确计时 — 找出最慢的系统调用
strace -T -e trace=read,write -p PID 2>&1 | awk '{print $NF, $0}' | sort -rn | head
#   -T = 显示每次调用耗时

# 场景2: 追踪特定错误(返回 -1 的系统调用)
strace -e trace=all -e fault=openat:error=ENOENT:when=1 ./prog
#   注入故障:openat 的第 1 次调用返回 ENOENT(测试错误处理)

# 场景3: 查看进程完整启动过程(含动态链接库加载)
strace -f -e trace=open,openat,stat -o startup.log ./prog
grep "ENOENT" startup.log | sort -u    # 找出所有找不到的文件(常见谜之 bug)

# 场景4: 追踪进程间通信(pipe/socketpair)
strace -f -e trace=network,read,write -s 2048 -p PID
#   -s 2048 捕获更多数据,看清消息内容

# 场景5: 统计 read/write 的吞吐量
strace -e trace=read,write -o >(
    awk '/^read/  {r+=$NF} /^write/ {w+=$NF}
         END {printf "read=%.1fMB write=%.1fMB\n", r/1e6, w/1e6}'
) ./prog

# 场景6: 追踪 SIGCHLD/SIGPIPE 等信号
strace -e trace=signal -p PID          # 只看信号处理

# 场景7: 分析 MySQL 卡顿原因
strace -c -f -p $(pgrep mysqld) & sleep 10; kill %1
#   10 秒内系统调用统计:fsync 多 → 磁盘;poll 多 → 网络等待

# 场景8: strace 输出太吵?只看失败的调用
strace -e trace=file -z -p PID         # -z 只打印返回非零的调用
strace -e trace=file -Z -p PID         # -Z 只打印返回失败的调用

6.5 lsof — 列出打开的文件(万物皆文件) ​

bash
lsof -p PID           # 某进程打开的所有文件
lsof -c nginx         # 某命令打开的所有文件
lsof -i :80           # 占用 80 端口的进程
lsof -i tcp:3306      # 指定协议和端口
lsof -i TCP:3306      # macOS 版本(大写)
lsof -u username      # 某用户打开的文件
lsof +D /var/log      # 某目录下被打开的文件
lsof /var/log/syslog  # 谁打开了这个文件

lsof -nP              # -n 不解析主机名, -P 不解析端口名(更快)
lsof -nP -iTCP -sTCP:LISTEN  # 列出所有监听端口

# 经典场景:
#   端口被占用?→ lsof -i :8080
#   磁盘无法卸载?→ lsof +D /mnt 看谁在使用
#   删了文件但空间没释放?→ lsof | grep deleted
#     → 进程还在持有已删除文件的 fd,kill 该进程即可释放

6.6 perf — Linux 性能剖析(Profiling) ​

bash
perf stat ./program              # 程序执行统计(CPU cycles、cache-misses等)
perf top                         # 实时函数级 CPU 热点(类似 top)
perf record -g ./program         # 记录采样 + 调用栈
perf report                      # 查看报告
perf record -g -p PID sleep 30   # 对运行中进程采样 30 秒

# 火焰图生成
perf record -F 99 -g -p PID -- sleep 30
perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg

6.7 dmesg — 内核环形缓冲区 ​

bash
dmesg | tail -50                      # 最近 50 条内核消息
dmesg -T                              # 人类可读时间戳
dmesg --level=err,warn                # 只看错误和警告
dmesg | grep -i "out of memory"       # OOM Killer 日志
dmesg | grep -i "error\|fail\|warn"

7. 网络诊断 ​

7.1 curl — 瑞士军刀级 HTTP 客户端 ​

bash
# === 基础 ===
curl https://api.example.com                    # GET 请求
curl -o file.json https://api.example.com       # 输出到文件
curl -O https://example.com/file.tar.gz         # 使用远程文件名保存
curl -s https://api.example.com                 # 静默模式(不显示进度)

# === 查看详情 ===
curl -v https://api.example.com                 # verbose(含请求头、TLS 握手)
curl -I https://api.example.com                 # 只取响应头
curl -w "\\nhttp_code:%{http_code}\\ntime_total:%{time_total}\\n" url
#   常用 -w 变量: http_code, time_total, time_connect, size_download

# === 方法与数据 ===
curl -X POST -d '{"key":"value"}' https://api.example.com
curl -X PUT -H "Content-Type: application/json" -d @data.json url
curl -X DELETE https://api.example.com/item/1

# === 认证与头部 ===
curl -H "Authorization: Bearer $TOKEN" url
curl -u user:pass https://api.example.com       # Basic Auth
curl -b "session=abc123" url                    # 发送 Cookie
curl -c cookies.txt url                         # 保存 Cookie 到文件
curl -b cookies.txt -c cookies.txt url          # 同时发送和保存

# === 进阶 ===
curl -L url                                      # 跟随重定向
curl -k https://self-signed.example.com          # 忽略证书验证(⚠️仅调试用)
curl --resolve example.com:443:1.2.3.4 https://example.com  # 指定 IP(不修改 /etc/hosts)
curl -x http://proxy:8080 url                    # 使用代理
curl --compressed url                            # 请求压缩传输
curl -s -o /dev/null -w "%{http_code}" url       # 只输出状态码

7.2 ss — Socket 统计(替代 netstat) ​

bash
ss -tlnp              # TCP 监听端口(最常用)
#   -t = TCP, -u = UDP, -l = listening, -n = 不解析名称, -p = 进程
ss -tlnp 'sport = :80'       # 指定端口

ss -s                 # 汇总统计
ss -antp              # 所有 TCP 连接(a=all)
ss -antp state established   # 只看已建立的连接
# 状态: established, time-wait, close-wait, listen, syn-sent, syn-recv

ss -t -o              # -o 显示 timer 信息(keepalive、重传超时等)
ss -4                 # 只显示 IPv4
ss -ti                # TCP 内部信息(mss、cwnd、rtt)

7.3 dig — DNS 诊断 ​

bash
dig example.com                          # 基础查询
dig example.com +short                   # 简短输出
dig @8.8.8.8 example.com                # 指定 DNS 服务器
dig -x 8.8.8.8                          # 反向解析(IP → 域名)
dig example.com ANY                      # 查询所有记录类型
dig example.com MX                       # 邮件记录
dig example.com NS                       # 域名服务器记录
dig example.com TXT                      # TXT 记录(SPF/DKIM 等)
dig +trace example.com                   # 追踪完整解析过程(从根开始)
dig example.com +stats                   # 只显示统计信息(查询时间等)

7.4 tcpdump — 抓包 ​

bash
tcpdump -i eth0                             # 监听 eth0
tcpdump -i any port 80                      # 任意网卡,80 端口
tcpdump -i any host 192.168.1.100           # 指定主机的流量
tcpdump -i any -w capture.pcap              # 写入 pcap 文件
tcpdump -r capture.pcap                     # 读取 pcap 文件
tcpdump -i any -A port 80                   # -A 以 ASCII 显示
tcpdump -i any -X port 80                   # -X 同时显示 hex 和 ASCII
tcpdump -i any tcp and port 443 and 'tcp[tcpflags] & tcp-syn != 0'
#   只看 TLS 的 SYN 包(连接建立)

# 不要抓包写文件在生产环境跑太久 — 文件会很大!
tcpdump -i any -W 5 -C 100 -w capture.pcap
#   -W 5 = 最多 5 个文件, -C 100 = 每个 100MB, 自动轮转

# === 进阶实战场景 ===
# 场景1: 抓取完整 HTTP 请求和响应(只看应用层)
tcpdump -i any -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
#   过滤掉 TCP 空负载的包(ACK-only),只看有数据的

# 场景2: 只看特定 HTTP 方法的请求
tcpdump -i any -A -s 0 'tcp port 80 and (tcp[((tcp[12]&0xf0)>>2):4] = 0x504f5354)'
#   0x504f5354 = "POST"(大端序)

# 场景3: DNS 查询追踪
tcpdump -i any -n port 53              # 所有 DNS 流量
tcpdump -i any -n 'udp port 53 and udp[10] & 0x80 = 0'
#   只看 DNS 查询(非响应),udp[10] 的第 8 位为 0 表示查询

# 场景4: TCP 握手/挥手分析(抓 SYN/FIN/RST)
tcpdump -i any -n 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0'
#   找出所有 TCP 连接建立、关闭、异常的包

# 场景5: TCP 重传分析(网络质量诊断)
tcpdump -i any -n 'tcp[tcpflags] & (tcp-syn|tcp-fin) == 0' -w raw.pcap
#   后面用: tshark -r raw.pcap -Y "tcp.analysis.retransmission"

# 场景6: 只抓某个 TCP 连接的四元组(精准过滤)
tcpdump -i any -n 'host 10.0.0.1 and host 10.0.0.2 and port 3306'

# 场景7: 抓取特定大小的包(找大象流)
tcpdump -i any -n 'greater 1400'       # 大于 1400 字节的包

# 场景8: 按网段过滤(CIDR)
tcpdump -i any -n 'net 10.0.0.0/8 and not net 10.0.1.0/24'

7.5 iptables — 包过滤/防火墙 ​

bash
# === 查看规则 ===
iptables -L -n -v                       # 列出规则(-n 不解析, -v 详细)
iptables -L INPUT -n -v                 # 只看 INPUT 链
iptables -t nat -L -n -v                # 查看 nat 表

# === 基础规则 ===
# 允许来自特定 IP 的 SSH
iptables -A INPUT -p tcp -s 10.0.0.1 --dport 22 -j ACCEPT

# 允许 lo 接口
iptables -A INPUT -i lo -j ACCEPT

# 允许已建立连接的回复包
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 阻止特定 IP
iptables -A INPUT -s 1.2.3.4 -j DROP

# 限制连接速率(防暴力破解)
iptables -A INPUT -p tcp --dport 22 -m recent --set --name ssh
iptables -A INPUT -p tcp --dport 22 -m recent --update \
  --seconds 60 --hitcount 5 --name ssh -j DROP

# === 保存/恢复 ===
iptables-save > /etc/iptables/rules.v4
iptables-restore < /etc/iptables/rules.v4

# ⚠️ 注意: iptables 正被 nftables 取代(两者不兼容)
# 现代 Linux 发行版(Ubuntu 20.04+, Debian 10+)默认使用 nftables

# === NAT / 端口转发 ===
# DNAT: 将外部请求转发到内部服务器
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.1.10:8080
# SNAT: 源地址转换(内网机器出公网)
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j SNAT --to-source 1.2.3.4
# MASQUERADE: 动态 SNAT(适合出口 IP 不固定的场景)
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE

# === 日志与调试 ===
# 记录被 DROP 的包(帮助排查规则问题)
iptables -A INPUT -j LOG --log-prefix "IPT-DROP: " --log-level 4
# 查看内核日志
dmesg | grep "IPT-DROP"

# 统计每条规则匹配次数
iptables -L -n -v                        # 第一列 pkts = 匹配包数

# 重置计数器
iptables -Z                              # 清零所有计数器
# 等待 5 秒后再看,就知道哪些规则在"活跃命中"

# === 常用安全策略组合 ===
# 默认拒绝 INPUT, 只放行必要端口
iptables -P INPUT DROP                    # 默认策略 DROP(⚠️ 远程操作先确保 SSH 已放行!)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 防止端口扫描
iptables -A INPUT -p tcp -m tcp --tcp-flags ALL NONE -j DROP     # NULL 扫描
iptables -A INPUT -p tcp -m tcp --tcp-flags ALL ALL -j DROP      # XMAS 扫描

# 删除规则技巧
iptables -L --line-numbers                # 显示规则编号
iptables -D INPUT 3                       # 删除 INPUT 链第 3 条规则
iptables -F INPUT                         # 清空 INPUT 链(⚠️ 谨慎)

7.6 nftables — 新一代防火墙(推荐) ​

bash
# 列出规则
nft list ruleset

# 创建表 + 链 + 规则
nft add table inet my_filter                  # inet = IPv4+IPv6 通用表
nft add chain inet my_filter input { type filter hook input priority 0\\; }
nft add rule inet my_filter input tcp dport 22 accept
nft add rule inet my_filter input tcp dport {80, 443} accept
nft add rule inet my_filter input ct state established,related accept
nft add rule inet my_filter input drop        # 默认拒绝

# 等同于上面 iptables 的 SSH 限速
nft add set inet my_filter ssh_users { type ipv4_addr\\; flags dynamic\\; timeout 60s\\; }
nft add rule inet my_filter input tcp dport 22 \
  update @ssh_users { ip saddr } \
  add @ssh_users { ip saddr limit rate over 5/minute } drop

7.7 nc — 网络瑞士军刀(TCP/UDP 调试) ​

bash
# 端口连通性测试
nc -zv 192.168.1.1 80           # TCP 端口
nc -zuv 192.168.1.1 53          # UDP 端口
nc -zv 192.168.1.1 20-30        # 端口范围扫描

# 简易 TCP Server/Client
nc -l 8080                      # 监听(一次性,收到连接后退出)
nc -lk 8080                     # 持续监听(-k = keep listening)
echo "hello" | nc localhost 8080  # 发送数据

# 文件传输
nc -l 1234 > received_file      # 接收端
nc host 1234 < file_to_send     # 发送端

# HTTP 裸请求
printf "GET / HTTP/1.0\\r\\n\\r\\n" | nc example.com 80

8. 加密/解密与编码 ​

8.1 openssl — 密码学全家桶 ​

8.1.1 证书/TLS 相关 ​

bash
# 查看证书
openssl x509 -in cert.pem -text -noout               # 证书详情
openssl x509 -in cert.pem -dates -noout              # 只看有效期
openssl x509 -in cert.pem -subject -noout            # 只看主体

# 远程检查站点证书
echo | openssl s_client -connect google.com:443 -servername google.com 2>/dev/null | openssl x509 -noout -dates
#   输出: notBefore=... notAfter=... (证书有效期)

# 查看完整 TLS 握手
openssl s_client -connect example.com:443 -tlsextdebug

# 支持的 TLS 版本/密码套件
openssl s_client -connect example.com:443 -tls1_2 2>&1 | grep -i "cipher"

# 生成自签名证书(开发/测试用)
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
#   -nodes = 不加密私钥(no DES)

# 从证书提取公钥
openssl x509 -in cert.pem -pubkey -noout > pubkey.pem

8.1.2 加密/解密 ​

bash
# 对称加密(AES-256-CBC)
openssl enc -aes-256-cbc -in plain.txt -out encrypted.bin -pass pass:MyPassword
openssl enc -aes-256-cbc -d -in encrypted.bin -out decrypted.txt -pass pass:MyPassword

# 从文件读取密码
openssl enc -aes-256-cbc -in plain.txt -out encrypted.bin -pass file:/path/to/password.txt

# 配合 base64(文本传输友好)
openssl enc -aes-256-cbc -a -in plain.txt -out encrypted.txt -pass pass:pwd
#   -a = base64 encode(armor),输出可读文本
openssl enc -aes-256-cbc -a -d -in encrypted.txt -out decrypted.txt -pass pass:pwd

# salt 和 PBKDF2(现代方式,推荐)
openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -in plain.txt -out enc.bin -pass pass:pwd
openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -d -in enc.bin -out dec.txt -pass pass:pwd

8.1.3 Hash 与 HMAC ​

bash
# 计算哈希
openssl dgst -sha256 file.bin              # SHA-256
openssl dgst -sha512 file.bin              # SHA-512
openssl dgst -md5 file.bin                 # MD5(⚠️ 不安全,仅用于校验)

# HMAC
openssl dgst -sha256 -hmac "secret-key" file.bin
#   也可以用管道: echo -n "message" | openssl dgst -sha256 -hmac "key"

# 随机数生成
openssl rand -hex 32                       # 32 字节随机 hex
openssl rand -base64 32                    # 32 字节 base64
openssl rand 16                            # 16 字节原始二进制

8.1.4 密钥生成 ​

bash
# RSA 私钥
openssl genrsa -out private.pem 2048       # 生成 2048 位 RSA 密钥
openssl genrsa -out private.pem 4096       # 4096 位

# 从私钥导出公钥
openssl rsa -in private.pem -pubout -out public.pem

# EC 密钥(更现代、更快)
openssl ecparam -genkey -name prime256v1 -out ec_private.pem
openssl ec -in ec_private.pem -pubout -out ec_public.pem
#   查看支持的曲线: openssl ecparam -list_curves

# Ed25519(最现代、最推荐)
openssl genpkey -algorithm Ed25519 -out ed25519_private.pem
openssl pkey -in ed25519_private.pem -pubout -out ed25519_public.pem

8.1.5 签名与验证 ​

bash
# 签名
openssl dgst -sha256 -sign private.pem -out signature.bin data.txt

# 验证
openssl dgst -sha256 -verify public.pem -signature signature.bin data.txt
#   输出: Verified OK

# Ed25519 签名
openssl pkeyutl -sign -inkey ed25519_private.pem -rawin -in msg.txt -out sig.bin
openssl pkeyutl -verify -pubin -inkey ed25519_public.pem -rawin -in msg.txt -sigfile sig.bin

8.1.6 PKI 实战:自建 CA 并签发证书 ​

bash
# Step 1: 创建 CA 根证书
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=MyOrg/CN=My Root CA"

# Step 2: 生成服务端私钥 + CSR
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
  -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=MyOrg/CN=myservice.local"

# Step 3: CA 签发证书(含 SAN 扩展)
cat > san.cnf << 'EOF'
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1 = myservice.local
DNS.2 = *.myservice.local
IP.1 = 127.0.0.1
EOF
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out server.crt -days 365 -extensions v3_req -extfile san.cnf

# Step 4: 验证证书链
openssl verify -CAfile ca.crt server.crt    # 输出: server.crt: OK

# Step 5: 查看证书 SAN
openssl x509 -in server.crt -text -noout | grep -A1 "Subject Alternative"

# 生成客户端证书(双向 TLS)
openssl req -new -key client.key -out client.csr \
  -subj "/CN=client-app"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out client.crt -days 365

8.1.7 TLS 连接诊断 ​

bash
# 测试 TLS 连接并查看完整握手
openssl s_client -connect example.com:443 -showcerts </dev/null

# 查看服务器证书链
echo | openssl s_client -connect example.com:443 -showcerts 2>/dev/null | \
  awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/' > chain.pem

# 测试特定 TLS 版本
openssl s_client -connect example.com:443 -tls1_2 </dev/null
openssl s_client -connect example.com:443 -tls1_3 </dev/null

# 列出服务器支持的密码套件
nmap --script ssl-enum-ciphers -p 443 example.com
# 或用: openssl s_client -connect example.com:443 -cipher 'ALL' </dev/null 2>&1

# 验证 OCSP 装订状态
openssl s_client -connect example.com:443 -status </dev/null | grep -A20 "OCSP"

# 基准测试(TLS 握手性能)
openssl s_time -connect example.com:443 -new -time 10
#   输出: 10 秒内完成了多少次握手,平均耗时等

8.1.8 其他常用操作 ​

bash
# 对比两个证书是否匹配同一私钥
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in key.pem | openssl md5
#   两个 MD5 一样 → 证书和私钥匹配

# 证书格式转换
openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM    # DER → PEM
openssl x509 -in cert.pem -outform DER -out cert.der                # PEM → DER
openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.p12    # PEM → PKCS12

# 查看 PKCS12 内容
openssl pkcs12 -in cert.p12 -info -noout

# 生成 DH 参数(用于 nginx 等)
openssl dhparam -out dhparam.pem 2048

# 安全的密码哈希(SHA-512 crypt,用于 /etc/shadow)
python3 -c "import crypt; print(crypt.crypt('mypassword', crypt.mksalt(crypt.METHOD_SHA512)))"

# 文件完整性校验
openssl dgst -sha256 large_file.iso     # 等同于 sha256sum

8.2 base64 — 编码/解码 ​

bash
echo -n "hello world" | base64              # 编码 → aGVsbG8gd29ybGQ=
echo -n "aGVsbG8gd29ybGQ=" | base64 -d     # 解码 → hello world

# 二进制文件
base64 image.png > image.b64                # 编码
base64 -d image.b64 > image.png             # 解码

# 去掉换行(方便嵌入 JSON 等)
echo -n "hello" | base64 -w 0              # Linux (-w = wrap)
echo -n "hello" | base64                   # macOS(默认不换行)

8.3 xxd / od / hexdump — 十六进制查看 ​

bash
xxd file.bin                               # 十六进制 + ASCII 并排
xxd -p file.bin                            # 纯十六进制(plain hexdump)
echo "48656c6c6f" | xxd -r -p              # hex → 二进制 → Hello
xxd -l 256 file.bin                        # 只看前 256 字节

od -A x -t x1z file.bin                    # 另一种 hexdump 风格
hexdump -C file.bin                        # 经典 hexdump 格式

9. 压缩与归档 ​

9.1 tar — 归档(Tape ARchive) ​

bash
# 创建
tar -cvf archive.tar dir/                  # 打包(不压缩)
tar -czvf archive.tar.gz dir/              # gzip 压缩(最常用)
tar -cjvf archive.tar.bz2 dir/             # bzip2 压缩(更小,更慢)
tar -cJvf archive.tar.xz dir/              # xz 压缩(最小说,最慢)
tar -czvf archive.tar.gz --exclude='*.log' dir/  # 排除文件

# 解压
tar -xvf archive.tar                       # 解压到当前目录
tar -xzvf archive.tar.gz                   # 解压 gzip
tar -xjvf archive.tar.bz2                  # 解压 bzip2
tar -xJvf archive.tar.xz                   # 解压 xz
tar -xzvf archive.tar.gz -C /target/dir    # 解压到指定目录

# 查看(不解压)
tar -tzvf archive.tar.gz                   # 列出内容
tar -tzvf archive.tar.gz | grep "filename" # 查找特定文件

# 记忆口诀:
#   c = create, x = extract, t = list
#   v = verbose, f = file
#   z = gzip,  j = bzip2,  J = xz

# pigz — 多线程 gzip(快很多!)
tar -c dir/ | pigz > archive.tar.gz        # 多核压缩
pigz -d archive.tar.gz | tar -x            # 多核解压

9.2 gzip / bzip2 / xz — 单独压缩 ​

bash
gzip file                # 压缩 → file.gz(原文件被删除)
gzip -k file             # 保留原文件
gzip -9 file             # 最高压缩比(1=最快, 9=最小, 默认 6)
gzip -d file.gz          # 解压
gunzip file.gz           # 同上

bzip2 file               # 压缩 → file.bz2
bzip2 -d file.bz2        # 解压

xz file                  # 压缩 → file.xz
xz -d file.xz            # 解压
xz -T0 file              # -T0 = 使用所有 CPU 核心(xz 5.2+)

# 查看压缩文件内容(不解压)
zcat file.gz             # gzip
bzcat file.bz2           # bzip2
xzcat file.xz            # xz

9.3 zip / unzip ​

bash
zip -r archive.zip dir/                      # 压缩目录
zip -e archive.zip file                      # 加密(会提示输入密码)
unzip archive.zip                            # 解压
unzip -l archive.zip                         # 列出内容
unzip archive.zip -d /target/dir             # 解压到指定目录
unzip -P password archive.zip                # 带密码解压

9.4 压缩格式对比 ​

格式压缩比速度多线程支持场景
gzip中快pigz日常使用、HTTP 传输
bzip2较高慢pbzip2长期归档
xz最高最慢xz -T发布包、长期存储
zstd高极快原生支持现代推荐(见下方)

9.5 zstd — 现代压缩(强烈推荐) ​

bash
# 需要安装: apt install zstd
zstd file                   # 压缩 → file.zst
zstd -d file.zst            # 解压
unzstd file.zst             # 同上
zstd -T0 file               # 使用所有 CPU 核心
zstd --ultra -22 file       # 最高压缩级别(1~22)
zstd -l file.zst            # 查看压缩文件信息

# tar 配合 zstd
tar --zstd -cvf archive.tar.zst dir/         # 压缩
tar --zstd -xvf archive.tar.zst              # 解压
# 或: tar -I 'zstd -T0' -cvf archive.tar.zst dir/

10. Shell 脚本进阶 ​

10.1 常用内置变量与结构 ​

bash
#!/bin/bash
set -euo pipefail
#   -e  任何命令失败(非零返回)立即退出
#   -u  使用未定义变量时报错
#   -o pipefail  管道中任何命令失败都返回失败

# 变量
echo "脚本名: $0"
echo "参数个数: $#"
echo "所有参数: $@"
echo "进程ID: $$"
echo "最后退出码: $?"

# 条件判断
if [[ -f "$file" ]]; then         # 文件存在且是普通文件
    echo "file exists"
fi
# 常用测试:
#   -f file    普通文件存在
#   -d dir     目录存在
#   -z "$str"  字符串为空
#   -n "$str"  字符串非空
#   "$a" == "$b"  字符串相等
#   "$a" != "$b"  字符串不等
#   -eq -ne -lt -le -gt -ge  数值比较

# 循环与遍历
for i in {1..10}; do echo $i; done
for file in *.txt; do process "$file"; done
while read -r line; do echo "$line"; done < file.txt

10.2 jq — JSON 处理利器 ​

bash
# 需要安装: apt install jq

jq '.' data.json                     # 格式化输出(美化)
jq -c '.' data.json                  # 紧凑输出(compact)
jq '.items[0].name' data.json        # 提取嵌套值
jq '.items[] | {name, price}' data.json  # 对象转换
jq '[.items[].name]' data.json       # 构建数组
jq '.[] | select(.price > 100)' data.json  # 条件过滤
jq 'length' data.json                # 数组长度
jq -r '.items[].name' data.json      # -r = raw(去掉引号)

# 实战:解析 API 响应
curl -s https://api.github.com/repos/torvalds/linux | jq -r '.stargazers_count'
#   输出: 123456

# 从 JSON 数组生成 shell 命令
jq -r '.[] | "curl -O \(.url)"' files.json | bash

10.3 yq — YAML 处理 ​

bash
# 需要安装: pip install yq (基于 jq)
cat config.yaml | yq '.database.host'
yq '.services | keys' docker-compose.yml

10.4 常用一行脚本(one-liners) ​

bash
# 批量重命名(加前缀)
for f in *.txt; do mv "$f" "prefix_$f"; done

# 批量重命名(替换扩展名)
for f in *.jpeg; do mv "$f" "${f%.jpeg}.jpg"; done

# 查找并替换所有文本文件中的字符串
find . -name "*.go" -exec sed -i 's/old_package/new_package/g' {} +

# 删除所有空行
sed -i '/^$/d' file.txt

# 当前目录下每个文件的行数
find . -type f | xargs wc -l | sort -rn

# 查看磁盘使用最大的 10 个目录
du -ah /path | sort -rh | head -10

# 生成随机密码(16 字符)
openssl rand -base64 12 | tr -d '=+/' | cut -c1-16
# 或
tr -dc 'A-Za-z0-9!@#$%^&*' < /dev/urandom | head -c 16

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

11. 现代化替代工具 ​

以下工具比传统命令更快/更友好,建议在开发机器上安装:

传统命令现代替代亮点
findfd快 5~10×,默认忽略 .gitignore,语法更直观
greprg (ripgrep)快 10~100×,默认忽略 .gitignore,自动递归
lsexa / lsd彩色、图标、Git 状态、树状视图
catbat语法高亮、行号、Git 变更标记、自动分页
dudust / ncdu人类可读的大小可视化
topbtm / bottomRust 重写,GPU 加速,更现代
diffdelta语法高亮的 diff,配合 git 使用
psprocs彩色输出,自动树状视图
sedsd更直观的查找替换语法
mantldr / cheat常用示例,比 man 精简 90%
digdog彩色 DNS 查询,JSON 输出
bash
# fd 示例
fd 'pattern'                    # 找包含 pattern 的文件名(默认递归、忽略.gitignore)
fd -e go                        # 按扩展名
fd -x wc -l                     # 对找到的每个文件执行命令
fd -t d                         # 只找目录
fd 'test' --exec go test {}     # Go 测试匹配的文件

# rg 示例
rg 'TODO'                       # 找所有 TODO
rg -t go 'func main'            # 只在 .go 文件中搜索
rg --files-with-matches 'TODO'  # 只列包含匹配的文件名
rg -C 5 'error'                 # 上下文 5 行
rg -l 'deprecated' | xargs -n1 sed -i 's/old/new/g'

# bat 示例
bat file.go                     # 语法高亮 + 行号
bat --show-all file             # 显示所有不可见字符
bat -p file                     # 纯文本模式(适合管道,不带行号和边框)

# tldr 示例
tldr tar                        # 显示 tar 的常用示例
tldr --list                     # 列出所有支持的命令(Linux 常用命令)

12. 常用组合模式速查 ​

需求命令
找最大的 5 个文件find . -type f -exec du -h {} + | sort -rh | head -5
找最老的 10 个文件find . -type f -printf '%T+ %p\n' | sort | head -10
统计代码行数find . -name '*.go' | xargs wc -l | tail -1
日志中 ERROR 及上下文grep -C 5 ERROR app.log
实时看日志中 ERRORtail -f app.log | grep --line-buffered ERROR
某进程使用的端口ss -tlnp | grep PID 或 lsof -i -P -n | grep PID
哪个进程在用某端口ss -tlnp | grep :8080 或 lsof -i :8080
发送 HTTP 请求并计时curl -w '\n%{time_total}s\n' -o /dev/null -s URL
生成自签名证书openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
递归替换文本find . -type f -name '*.txt' -exec sed -i 's/old/new/g' {} +
查看历史命令history | grep keyword 或 Ctrl+R
进程卡在哪个系统调用strace -p PID
磁盘 IO 瓶颈iostat -x 1 → 看 %util 和 await

参考 ​

批注模式

💬 文章评论

暂无评论,来说点什么吧 👇

编程学习笔记