磁盘、挂载与容量规划
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read431 words

磁盘、挂载与容量规划

很多事故不是程序崩了,而是磁盘满了、挂载错了、日志把系统盘吃爆了。

存储分层

graph TD A[系统盘 /] --> B[OS、软件包、systemd] C[数据盘 /data] --> D[数据库文件、用户上传] E[对象存储 S3/GCS] --> F[备份、归档、静态资源] B -->|日志| G[/var/log — 需设上限] D -->|每日备份| E

磁盘状态诊断命令

# 查看各分区使用率(常用)
df -h
# 例:/dev/sda1  40G  36G  4G  90%  /  ← 危险,需清理
# 查看磁盘设备与分区结构
lsblk
# 例:sda → sda1(系统盘) / sdb → sdb1(数据盘,未挂载)
# 找出最大的目录(排查磁盘占用)
du -sh /var/log/* | sort -rh | head -10
du -sh /opt/* | sort -rh | head -10
# 查看当前挂载点
mount | grep ^/dev
# 查看 inode 使用率(小文件过多也会导致磁盘"满")
df -i

数据盘挂载(持久化配置)

云主机新增数据盘后,默认不会自动挂载,需手动配置:

# 1. 查看新磁盘设备名
lsblk
# → sdb(未挂载的数据盘)
# 2. 格式化(只在全新磁盘上执行,会清除数据!)
sudo mkfs.ext4 /dev/sdb
# 3. 获取 UUID(比设备名稳定)
sudo blkid /dev/sdb
# → /dev/sdb: UUID="a1b2c3d4-..." TYPE="ext4"
# 4. 创建挂载点
sudo mkdir -p /data
# 5. 临时挂载(验证)
sudo mount /dev/sdb /data
df -h /data   # 确认挂载成功
# 6. 写入 /etc/fstab(永久挂载,重启后生效)
echo "UUID=a1b2c3d4-xxxx  /data  ext4  defaults,noatime  0  2" | sudo tee -a /etc/fstab
# 7. 验证 fstab 语法(避免写错导致无法启动)
sudo mount -a && echo "fstab 验证通过"

/etc/fstab 字段说明:

字段 示例 说明
设备 UUID=a1b2... 用 UUID 而非 /dev/sdb(设备名可能变)
挂载点 /data 提前创建目录
文件系统 ext4 最常用,稳定成熟
挂载选项 defaults,noatime noatime 减少写操作,提升性能
dump 0 0=不做 dump 备份
fsck顺序 2 1=系统盘,2=数据盘,0=跳过检查

日志容量控制(防止系统盘被日志撑满)

logrotate(应用日志轮转)

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily               # 每日轮转
rotate 14           # 保留 14 份
compress            # 旧日志压缩
delaycompress       # 上一份先不压缩(给正在读取的进程)
missingok           # 日志文件不存在时不报错
notifempty          # 空文件不轮转
create 0640 app app # 新日志文件权限
postrotate
systemctl reload myapp 2>/dev/null || true
endscript
}
# 测试 logrotate 配置
sudo logrotate -d /etc/logrotate.d/myapp   # -d 是 dry-run,不实际执行
sudo logrotate -f /etc/logrotate.d/myapp   # 强制执行(测试用)

systemd journal 大小限制

# 查看 journal 当前占用
journalctl --disk-usage
# 限制 journal 最大占用(写入 /etc/systemd/journald.conf)
sudo tee -a /etc/systemd/journald.conf <<'EOF'
[Journal]
SystemMaxUse=500M
SystemKeepFree=1G
MaxRetentionSec=30day
EOF
sudo systemctl restart systemd-journald
journalctl --disk-usage   # 确认生效

磁盘告警脚本

#!/usr/bin/env bash
# check_disk.sh — 磁盘告警(适合放入 cron 每 5 分钟)
set -euo pipefail
WARN_PCT=80
CRIT_PCT=90
WEBHOOK="${ALERT_WEBHOOK:-}"
alert() {
echo "[ALERT] $*" >&2
[[ -n "$WEBHOOK" ]] && curl -sf -X POST -H 'Content-type: application/json' \
-d "{\"text\":\"[DISK ALERT] $*\"}" "$WEBHOOK" || true
}
df -h --output=pcent,target | tail -n +2 | while read -r pct mount; do
pct_num="${pct//%/}"
if (( pct_num >= CRIT_PCT )); then
alert "CRITICAL: $mount 使用率 ${pct},立即清理!"
elif (( pct_num >= WARN_PCT )); then
alert "WARNING: $mount 使用率 ${pct},需要关注"
fi
done

常见误区

误区 正确做法
数据和日志都放系统盘 数据库/上传文件挂到独立数据盘,日志设轮转上限
磁盘满了才发现 设置 80% 告警,90% 告警升级
fstab 写设备名(/dev/sdb UUID,设备名在重启后可能变化
忘记测试 fstab 语法 写入后立即 mount -a 验证,错误语法会导致系统无法启动

本节执行清单

下一节数据库与文件备份策略——容量只是前提,备份才是底线。