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/dir1.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 -rf1.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 -102.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 # 不解压搜索 zip3.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}' file3.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.txt4. 用户与权限
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 file4.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_202607115.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.svg6.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 } drop7.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 808. 加密/解密与编码
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.pem8.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:pwd8.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.pem8.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.bin8.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 3658.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 # 等同于 sha256sum8.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 # xz9.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.txt10.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 | bash10.3 yq — YAML 处理
bash
# 需要安装: pip install yq (基于 jq)
cat config.yaml | yq '.database.host'
yq '.services | keys' docker-compose.yml10.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.txt11. 现代化替代工具
以下工具比传统命令更快/更友好,建议在开发机器上安装:
| 传统命令 | 现代替代 | 亮点 |
|---|---|---|
find | fd | 快 5~10×,默认忽略 .gitignore,语法更直观 |
grep | rg (ripgrep) | 快 10~100×,默认忽略 .gitignore,自动递归 |
ls | exa / lsd | 彩色、图标、Git 状态、树状视图 |
cat | bat | 语法高亮、行号、Git 变更标记、自动分页 |
du | dust / ncdu | 人类可读的大小可视化 |
top | btm / bottom | Rust 重写,GPU 加速,更现代 |
diff | delta | 语法高亮的 diff,配合 git 使用 |
ps | procs | 彩色输出,自动树状视图 |
sed | sd | 更直观的查找替换语法 |
man | tldr / cheat | 常用示例,比 man 精简 90% |
dig | dog | 彩色 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 |
| 实时看日志中 ERROR | tail -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 |
参考
- explainshell.com — 输入命令行,逐部分解释含义
- tldr.sh — 命令常用示例速查
- cheat.sh — curl cheat.sh/tar 即可获取速查
- Linux Kernel Map — 内核交互全景图
- Brendan Gregg's Perf Tools — Linux 性能观测工具大全
- jqlang/jq Manual
- OpenSSL Cookbook
登录后即可发表评论 👇