强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Alpine Linux 完全指南 / 第 13 章:故障排查

第 13 章:故障排查

常见问题诊断与解决方法、musl 兼容性处理和系统调试技巧。

13.1 musl 兼容性问题

常见错误及解决

错误信息 原因 解决方案
No such file or directory 程序链接 glibc 动态链接器 安装 gcompat 或重编译
Error relocating: symbol not found glibc 专有符号 安装 gcompat
Segmentation fault glibc 二进制不兼容 使用容器隔离或重编译
DNS resolution failed musl DNS 实现差异 检查 resolv.conf

gcompat 兼容层

# 安装 glibc 兼容层
apk add gcompat

# 设置 glibc 链接器路径
export LD_LIBRARY_PATH=/lib64:/usr/lib64

# 验证 glibc 程序运行
ldd /path/to/glibc/binary
# 应显示 /lib64/ld-linux-x86-64.so.2

# 常见需 gcompat 的软件
# - Steam
# - 某些 Electron 应用
# - 部分商业软件
# - 某些预编译二进制

DNS 解析问题

# musl 的 DNS 解析行为与 glibc 不同
# musl 不支持 nsswitch.conf 的复杂配置

# 问题:某些程序无法解析主机名
# 解决:检查 /etc/resolv.conf
cat /etc/resolv.conf
# 确保包含有效的 nameserver

# 问题:DNS 超时
# musl 默认不支持 search 域的复杂解析
# 解决方案:
echo "options single-request-reopen" >> /etc/resolv.conf

# 问题:IPv6 DNS 解析问题
# musl 优先尝试 IPv6
# 解决:
echo "options single-request" >> /etc/resolv.conf

# DNS 调试
apk add bind-tools
dig example.com +trace
nslookup example.com 8.8.8.8

字符编码问题

# musl 的 locale 支持有限
# 默认只有 C/POSIX locale

# 安装 locale 支持
apk add musl-locales

# 设置 locale
export MUSL_LOCPATH=/usr/share/i18n/locales/musl
export LANG=zh_CN.UTF-8
export LC_ALL=zh_CN.UTF-8

# 查看可用 locale
ls /usr/share/i18n/locales/musl/

# 持久化配置
cat >> /etc/profile.d/locale.sh << 'EOF'
export MUSL_LOCPATH=/usr/share/i18n/locales/musl
export LANG=zh_CN.UTF-8
EOF

静态链接解决兼容性

# 编译静态链接的程序,避免运行时依赖

# C/C++
gcc -static -o myapp myapp.c
# 或使用 musl-gcc
musl-gcc -static -o myapp myapp.c

# Go
CGO_ENABLED=0 go build -o myapp .

# Rust
cargo build --release --target x86_64-unknown-linux-musl

# 检查静态链接
file myapp
# 应显示 "statically linked"
ldd myapp
# 应显示 "not a dynamic executable"

13.2 启动问题排查

引导失败

# 1. 从 Live CD 启动
# 2. 挂载根分区
mount /dev/sda2 /mnt
mount /dev/sda1 /mnt/boot

# 3. chroot 进入系统
chroot /mnt /bin/sh

# 4. 检查关键配置
cat /etc/fstab           # 检查文件系统配置
cat /etc/network/interfaces  # 检查网络配置
cat /etc/conf.d/*         # 检查服务配置

# 5. 检查内核和 initramfs
ls -la /boot/

# 6. 重新安装引导
extlinux --install /boot
dd if=/usr/share/syslinux/mbr.bin of=/dev/sda bs=440 count=1

# 7. 检查文件系统
fsck /dev/sda2

服务启动失败

# 查看服务状态
rc-service nginx status

# 查看服务日志
tail -100 /var/log/messages | grep nginx

# 手动启动服务查看错误
nginx -t  # 测试配置文件语法
nginx     # 前台运行查看输出

# 详细日志模式
# /etc/init.d/nginx
# 在 start 函数前添加:
# set -x

# 检查依赖
rc-service -D nginx  # 显示依赖树

# 重建服务依赖
rc-update --update

13.3 网络问题排查

网络诊断流程

# 1. 检查接口状态
ip link show
# 确保接口 UP

# 2. 检查 IP 地址
ip addr show
# 确保有正确 IP

# 3. 检查路由
ip route show
# 确保有默认路由

# 4. 测试本地连通性
ping 127.0.0.1
ping <网关IP>

# 5. 测试外网连通性
ping 8.8.8.8

# 6. 测试 DNS
nslookup example.com
dig @8.8.8.8 example.com

# 7. 测试端口连通性
nc -zv example.com 80
curl -v https://example.com

# 8. 检查防火墙规则
iptables -L -n -v
iptables -L -n -v -t nat

常见网络问题

问题 可能原因 解决方案
无 IP 地址 DHCP 失败 检查网络配置、DHCP 服务
有 IP 无网络 路由/DNS 问题 检查路由表和 resolv.conf
DNS 解析失败 DNS 配置错误 检查 /etc/resolv.conf
端口无法访问 防火墙阻止 检查 iptables 规则
连接超时 MTU 问题 降低 MTU 值

抓包分析

# 安装 tcpdump
apk add tcpdump

# 抓取 HTTP 流量
tcpdump -i eth0 -nn port 80 -A

# 抓取 DNS 查询
tcpdump -i eth0 -nn port 53

# 保存到文件分析
tcpdump -i eth0 -nn -w /tmp/capture.pcap

# 安装 Wireshark CLI
apk add tshark
tshark -r /tmp/capture.pcap

13.4 性能问题排查

CPU 问题

# 查看 CPU 使用率
top -bn1 | head -20
htop  # 需安装

# 查看每个 CPU 核心
mpstat -P ALL 1 5  # 需安装 sysstat

# 进程 CPU 使用率排序
ps aux --sort=-%cpu | head -10

# CPU 密集型进程追踪
strace -c -p <PID>  # 统计系统调用
perf top             # 性能分析(需安装)

内存问题

# 内存使用概览
free -h

# 详细内存信息
cat /proc/meminfo

# 进程内存使用排序
ps aux --sort=-%mem | head -10

# 查看进程内存映射
cat /proc/<PID>/smaps

# 内存泄漏检测
apk add valgrind
valgrind --leak-check=full ./myapp

磁盘 IO 问题

# IO 统计
iostat -x 1 5  # 需安装 sysstat

# 查看 IO 最多的进程
iotop  # 需安装 iotop

# 磁盘使用检查
df -h
du -sh /* | sort -h | tail -10

网络性能

# 带宽测试
apk add iperf3
# 服务端
iperf3 -s
# 客户端
iperf3 -c <服务端IP>

# 延迟测试
ping -c 100 <目标IP> | tail -1

# 连接数统计
ss -s
ss -tlnp | wc -l

13.5 日志分析

# 系统日志
tail -f /var/log/messages

# 认证日志
grep "Failed password" /var/log/messages
grep "Accepted publickey" /var/log/messages

# 内核日志
dmesg | tail -50
dmesg -T | grep -i error  # 带时间戳

# 服务特定日志
journalctl -u nginx  # 如果有 systemd

# 日志分析脚本
cat > /usr/local/bin/log-analyzer << 'SCRIPT'
#!/bin/sh
echo "=== 最近登录失败 ==="
grep "Failed" /var/log/messages 2>/dev/null | tail -10

echo ""
echo "=== 最近错误 ==="
grep -i "error\|critical\|fatal" /var/log/messages | tail -10

echo ""
echo "=== 磁盘空间 ==="
df -h | grep -E '^/dev' | awk '{print $5, $6}'

echo ""
echo "=== 内存使用 ==="
free -h

echo ""
echo "=== 负载 ==="
uptime
SCRIPT
chmod +x /usr/local/bin/log-analyzer

13.6 容器故障排查

# Docker 容器无法启动
docker logs <container>
docker inspect <container>

# 进入运行中的容器
docker exec -it <container> sh

# 进入已停止的容器
docker run -it --rm --entrypoint sh <image>

# 检查容器资源
docker stats <container>
docker inspect --format='{{.State.Pid}}' <container>
cat /proc/<PID>/cgroup

# 网络问题
docker network inspect <network>
docker exec <container> ping <host>
docker exec <container> cat /etc/resolv.conf

# 存储问题
docker exec <container> df -h
docker system df
docker system prune -a

13.7 包管理问题

# 错误: ERROR: unsatisfiable constraints
# 原因: 包依赖冲突
# 解决:
apk update
apk add --simulate package-name  # 预览安装
apk fix package-name  # 尝试修复

# 错误: unable to select packages
# 原因: 包名错误或不在当前仓库
apk search keyword  # 搜索正确包名
cat /etc/apk/repositories  # 检查仓库配置

# 错误: BAD signature
# 原因: 密钥过期或损坏
apk update --allow-untrusted  # 不推荐,仅调试

# 正确方式:更新密钥
apk fix --upgrade alpine-keys
apk update

# 缓存损坏
rm -rf /var/cache/apk/*
apk update

13.8 调试工具速查

工具 安装命令 用途
strace apk add strace 系统调用追踪
ltrace apk add ltrace 库函数追踪
gdb apk add gdb 程序调试
ldd 内置 查看动态库依赖
file 内置 文件类型识别
readelf 内置 ELF 文件分析
objdump apk add binutils 二进制分析
tcpdump apk add tcpdump 网络抓包
perf apk add linux-tools 性能分析
valgrind apk add valgrind 内存检测

13.9 常见问题 FAQ

Q: 为什么 glibc 编译的程序在 Alpine 上运行报 “No such file or directory”? A: 程序的 ELF 解释器指向 /lib64/ld-linux-x86-64.so.2(glibc),而 Alpine 使用 /lib/ld-musl-x86_64.so.1。解决:安装 gcompat 或重新编译。

Q: 如何在 Alpine 上运行 Ubuntu 的 deb 包? A: 不推荐。应寻找 Alpine 原生包或源码编译。必要时可使用容器运行 Ubuntu 环境。

Q: Docker 中使用 Alpine 时 musl 导致的问题? A: 使用多阶段构建,在 Alpine 环境中编译程序;或使用 gcompat 包;或静态链接编译。

Q: 如何调试 OpenRC 服务? A: 使用 rc-service <name> -d start(调试模式),或直接运行服务命令查看输出。

13.10 故障排查清单

  • 确认 Alpine 版本:cat /etc/alpine-release
  • 检查系统日志:tail -100 /var/log/messages
  • 检查磁盘空间:df -h
  • 检查内存:free -h
  • 检查网络:ip addr show && ip route show
  • 检查 DNS:nslookup example.com
  • 检查防火墙:iptables -L -n
  • 检查服务状态:rc-status
  • 检查最近更新:apk version -l '<'

扩展阅读


上一章第 12 章:系统加固 下一章第 14 章:嵌入式应用