飞牛os安装时选择的空间较小(16G),刚开始的时候是够用的,随着使用时间剩余空间越来越少,占用达到88%以上。最近在学习lxc容器,在nas上练手,导致系统分区占用100%,在找回空间的过程中,顺便把空间占用减小到60%。

查看磁盘整体使用情况

df -h
确认哪个分区(比如 / 根分区或 /var 分区)已经满了或接近满。

清理系统。

1
2
3
4
5
6
7
8
9
10
11
12
# 检查 apt 缓存(通常能清理几百 MB)
sudo du -sh /var/cache/apt

# 检查临时文件
sudo du -sh /tmp

# 检查 snap 包(如果装了 snap)
sudo du -sh /var/lib/snapd

# 检查下载目录或用户目录
sudo du -sh /root
sudo du -sh /home/* 2>/dev/null

找到占用空间最大的目录

1
sudo du -sh /* --exclude=/vol1 --exclude=/vol2 --exclude=/vol02 2>/dev/null | sort -hr | head -15

排除了挂载的大硬盘 /vol1, /vol2, /vol02,这样看根分区更清楚。需要的时候比较长。
docker,lxc之类默认在/var/lib下面。

查找大于 100MB 的大文件
直接搜索根分区下所有大于 100MB 的文件:

1
sudo find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | awk '{print $5, $9}' | sort -hr | head -20

这个命令会直接列出所有大文件的路径和大小,是最快定位问题的方法。

找到占用空间的主要是这三个:/usr,/swapfile,/var。

  • /swapfile
    有 4.1GB —— 是系统 swap(虚拟内存)。nas的物理内存只有 4GB,系统创建了一个 4.1GB 的 swap 文件来辅助内存。这部分是正常的,不建议删除。
  • /usr
    7.1GB —— 系统程序,不能动。
  • /var
    3.2GB —— 这是可以清理的部分。
1
2
3
4
5
6
7
8
9
10
11
# 查看 /var 下面哪些子目录大
sudo du -sh /var/* 2>/dev/null | sort -hr | head -10
# 清理 apt 包缓存(通常能释放几百 MB)
sudo apt clean
sudo apt autoremove --purge -y

# 清理 journal 日志(保留最近 3 天)
sudo journalctl --vacuum-time=3d

# 如果有 snap 残留
sudo rm -rf /var/lib/snapd/cache/*

解决方案

16GB 根分区对于 Debian + fnOS + Docker 来说确实太小了。大硬盘(/vol1、/vol2)有几百 GB 空间,把 swapfile 迁移到 /vol1 或 /vol2,可以释放根分区 4.1GB 空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 关闭当前 swap
sudo swapoff /swapfile

# 在大硬盘上创建新的 swap 文件(例如在 /vol1 上创建 4GB swap)
sudo fallocate -l 4G /vol1/swapfile
sudo chmod 600 /vol1/swapfile
sudo mkswap /vol1/swapfile

# 启用新 swap
sudo swapon /vol1/swapfile

# 删除旧的 swapfile
sudo rm /swapfile

# 更新 /etc/fstab,把原来的 /swapfile 改成 /vol1/swapfile
sudo sed -i 's/\/swapfile/\/vol1\/swapfile/g' /etc/fstab

这样根分区可以立即释放 4.1GB 空间,使用率从 88% 降到 60% 左右,后续再清理一下 /var,就能稳定在 50-60% 的水平。

验证并查看释放的空间

1
2
swapon --show   # 应该显示 /vol1/swapfile
df -h / # 检查根分区的可用空间,应该会从 1.9G 增加到 6G 左右

完成后:

  • 根分区 (/):从 88% 使用率降低到 ~60%。
  • 可用空间:从 1.9GB 增加到 ~6GB。
  • 性能:将 swap 放在大硬盘上,对日常使用没有任何负面影响。

nas上系统分区主要用于放置操作系统,数据独立存放,docker之类占用空间大的都放在大容量存储上,lxc也同样需要放在大容器存储上,不然会把系统分区占满。
本文由deepseek指导,并实操通过。

2026年9月更新:

清理旧内核

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#!/bin/bash
#
# clean-old-kernels.sh
# 清理飞牛 fnOS 旧内核,保留当前内核 + 最近 1 个旧内核
# 同时清理日志和 apt 缓存
#
# 用法:
# sudo ./clean-old-kernels.sh # 交互确认后执行
# sudo ./clean-old-kernels.sh --dry-run # 只显示要删什么,不实际删
# sudo ./clean-old-kernels.sh --yes # 跳过确认直接执行
#
# 警告:内核操作有风险,运行前请确保系统可正常重启。
#

set -euo pipefail

# ---------- 参数解析 ----------
DRY_RUN=0
AUTO_YES=0
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=1 ;;
--yes|-y) AUTO_YES=1 ;;
-h|--help)
echo "用法: $0 [--dry-run] [--yes]"
exit 0
;;
*)
echo "未知参数: $arg"
exit 1
;;
esac
done

# ---------- 颜色 ----------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log() { echo -e "${BLUE}[信息]${NC} $*"; }
warn() { echo -e "${YELLOW}[警告]${NC} $*"; }
ok() { echo -e "${GREEN}[完成]${NC} $*"; }
err() { echo -e "${RED}[错误]${NC} $*" >&2; }

# ---------- 前置检查 ----------
if [[ $EUID -ne 0 ]]; then
err "请用 root 运行(sudo $0)"
exit 1
fi

MODULES_DIR="/usr/lib/modules"
MODULES_TRIM_DIR="/usr/lib/modules_trim"
BOOT_DIR="/boot"

CURRENT_KERNEL="$(uname -r)"
log "当前运行内核: ${CURRENT_KERNEL}"

# 收集所有内核版本(以 /usr/lib/modules 为准)
mapfile -t ALL_KERNELS < <(
ls -1 "$MODULES_DIR" 2>/dev/null | grep -E '^[0-9]' | sort -V
)

if [[ ${#ALL_KERNELS[@]} -eq 0 ]]; then
err "在 $MODULES_DIR 下没找到任何内核目录,退出。"
exit 1
fi

log "发现内核版本共 ${#ALL_KERNELS[@]} 个:"
for k in "${ALL_KERNELS[@]}"; do
printf " - %s\n" "$k"
done

# ---------- 计算要保留的版本 ----------
# 保留策略:当前内核 + 最近 1 个旧内核(按版本排序后,当前内核之前的那个)
KEEP_LIST=("$CURRENT_KERNEL")

# 找出比当前内核"旧"的最近一个
PREV_KERNEL=""
for k in "${ALL_KERNELS[@]}"; do
if [[ "$k" == "$CURRENT_KERNEL" ]]; then
break
fi
PREV_KERNEL="$k"
done

if [[ -n "$PREV_KERNEL" ]]; then
KEEP_LIST+=("$PREV_KERNEL")
fi

log "将保留以下内核:"
for k in "${KEEP_LIST[@]}"; do
printf " ${GREEN}${NC} %s\n" "$k"
done

# ---------- 计算要删除的版本 ----------
DELETE_LIST=()
for k in "${ALL_KERNELS[@]}"; do
skip=0
for keep in "${KEEP_LIST[@]}"; do
if [[ "$k" == "$keep" ]]; then
skip=1
break
fi
done
[[ $skip -eq 0 ]] && DELETE_LIST+=("$k")
done

if [[ ${#DELETE_LIST[@]} -eq 0 ]]; then
ok "没有需要删除的旧内核。"
else
warn "将删除以下旧内核:"
for k in "${DELETE_LIST[@]}"; do
printf " ${RED}${NC} %s\n" "$k"
done
fi

# ---------- 安全检查:确保当前内核目录存在 ----------
if [[ ! -d "$MODULES_DIR/$CURRENT_KERNEL" ]]; then
err "当前内核目录 $MODULES_DIR/$CURRENT_KERNEL 不存在!为安全起见,中止。"
exit 1
fi
ok "当前内核目录存在,安全检查通过。"

# ---------- 确认 ----------
if [[ $DRY_RUN -eq 1 ]]; then
warn "干跑模式(--dry-run),不实际删除。"
fi

if [[ $DRY_RUN -eq 0 && $AUTO_YES -eq 0 ]]; then
echo
read -r -p "确认执行删除?输入 yes 继续: " CONFIRM
if [[ "$CONFIRM" != "yes" ]]; then
warn "已取消。"
exit 0
fi
fi

# ---------- 执行删除 ----------
do_rm() {
local path="$1"
if [[ -e "$path" ]]; then
if [[ $DRY_RUN -eq 1 ]]; then
echo " [dry-run] rm -rf $path"
else
rm -rf "$path"
echo " 已删除: $path"
fi
fi
}

do_rm_file() {
local path="$1"
if [[ -e "$path" ]]; then
if [[ $DRY_RUN -eq 1 ]]; then
echo " [dry-run] rm -f $path"
else
rm -f "$path"
echo " 已删除: $path"
fi
fi
}

if [[ ${#DELETE_LIST[@]} -gt 0 ]]; then
echo
log "开始删除旧内核..."
for k in "${DELETE_LIST[@]}"; do
echo "→ 处理内核: $k"
do_rm "$MODULES_DIR/$k"
do_rm "$MODULES_TRIM_DIR/$k"
do_rm_file "$BOOT_DIR/config-$k"
do_rm_file "$BOOT_DIR/initrd.img-$k"
do_rm_file "$BOOT_DIR/System.map-$k"
do_rm_file "$BOOT_DIR/vmlinuz-$k"
done
ok "旧内核删除完成。"
fi

# ---------- 清理日志和缓存 ----------
echo
log "清理日志和 apt 缓存..."

if [[ $DRY_RUN -eq 1 ]]; then
echo " [dry-run] journalctl --vacuum-size=50M"
echo " [dry-run] rm -rf /var/log/trim_app_center/*"
echo " [dry-run] rm -rf /var/log/trim-connect/*"
echo " [dry-run] truncate -s 0 /var/log/kern.log ..."
echo " [dry-run] rm -f /var/log/*.gz /var/log/*.1"
echo " [dry-run] apt clean"
echo " [dry-run] apt autoremove --purge"
else
journalctl --vacuum-size=50M 2>/dev/null || warn "journalctl 清理失败"
rm -rf /var/log/trim_app_center/* 2>/dev/null || true
rm -rf /var/log/trim-connect/* 2>/dev/null || true
for f in kern.log syslog user.log mail.log cron.log; do
[[ -f "/var/log/$f" ]] && truncate -s 0 "/var/log/$f"
done
rm -f /var/log/*.gz /var/log/*.1 2>/dev/null || true
apt clean 2>/dev/null || true
apt autoremove --purge -y 2>/dev/null || true
fi

# ---------- 结果汇总 ----------
echo
log "清理后状态:"
df -h / | tail -1
echo
du -sh "$MODULES_DIR" "$MODULES_TRIM_DIR" "$BOOT_DIR" 2>/dev/null || true
echo
log "保留的内核:"
for k in "${KEEP_LIST[@]}"; do
printf " ${GREEN}${NC} %s\n" "$k"
done

echo
ok "全部完成。建议重启验证系统可正常启动。"
warn "如果重启异常,在 GRUB 菜单选择保留的旧内核 ${PREV_KERNEL:-无} 进入系统修复。"

保存为/root/clean-old-kernels.sh
chmod +x /root/clean-old-kernels.sh
先干跑看要删什么
/root/clean-old-kernels.sh --dry-run
确认无误后正式执行
/root/clean-old-kernels.sh