优化交换空间管理,确保安全重建交换文件以避免内存溢出
This commit is contained in:
+72
-31
@@ -589,43 +589,84 @@ if [ "${SWAP_DIFF#-}" -le 5 ]; then
|
|||||||
# 显示交换空间信息
|
# 显示交换空间信息
|
||||||
free -h | tee -a $LOG_FILE
|
free -h | tee -a $LOG_FILE
|
||||||
else
|
else
|
||||||
# 如果不存在交换空间或大小不同,则进行处理
|
# 交换空间大小不符或不存在,需要重建
|
||||||
|
# 关键修复:旧版直接对正在使用的交换执行 swapoff,会在内存紧张时把换出页
|
||||||
|
# 强行搬回内存,触发 OOM Killer 杀死 swapoff(exit 137),进而导致后续
|
||||||
|
# rm/dd/mkswap/swapon 连锁失败。
|
||||||
|
# 解决方案:先创建并启用一个新的交换文件作为“缓冲”,再关闭旧交换,
|
||||||
|
# 全程保证始终有足够的交换空间容纳换出页,避免 OOM。
|
||||||
if [ "$CURRENT_SWAP_TOTAL" -gt "0" ]; then
|
if [ "$CURRENT_SWAP_TOTAL" -gt "0" ]; then
|
||||||
log "${YELLOW}系统已有交换空间但大小不符(${CURRENT_SWAP_TOTAL}MB),准备清理现有交换空间...${NC}"
|
log "${YELLOW}系统已有交换空间但大小不符(${CURRENT_SWAP_TOTAL}MB),准备安全重建...${NC}"
|
||||||
|
|
||||||
# 获取所有交换设备
|
|
||||||
SWAP_DEVICES=$(swapon --show=NAME --noheadings)
|
|
||||||
|
|
||||||
# 清理所有活跃的交换空间
|
|
||||||
for DEVICE in $SWAP_DEVICES; do
|
|
||||||
log "${YELLOW}关闭交换空间: $DEVICE${NC}"
|
|
||||||
swapoff "$DEVICE"
|
|
||||||
done
|
|
||||||
|
|
||||||
# 从fstab中移除所有交换空间条目(保留备份)
|
|
||||||
cp /etc/fstab /etc/fstab.bak
|
|
||||||
log "${GREEN}备份了/etc/fstab文件${NC}"
|
|
||||||
sed -i '/swap/d' /etc/fstab
|
|
||||||
|
|
||||||
# 删除交换文件
|
|
||||||
if [ -f /swapfile ]; then
|
|
||||||
log "${YELLOW}删除现有交换文件...${NC}"
|
|
||||||
rm -f /swapfile
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "${GREEN}所有现有交换空间已清理${NC}"
|
|
||||||
else
|
else
|
||||||
log "${YELLOW}系统未配置交换空间,准备创建...${NC}"
|
log "${YELLOW}系统未配置交换空间,准备创建...${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 创建新的交换文件
|
# 备份fstab
|
||||||
log "${GREEN}创建${SWAP_SIZE}MB大小的交换文件...${NC}"
|
cp /etc/fstab /etc/fstab.bak
|
||||||
dd if=/dev/zero of=/swapfile bs=1M count=$SWAP_SIZE status=progress
|
log "${GREEN}备份了/etc/fstab文件${NC}"
|
||||||
chmod 600 /swapfile
|
|
||||||
mkswap /swapfile
|
|
||||||
swapon /swapfile
|
|
||||||
|
|
||||||
# 设置开机自动挂载
|
# 尽量释放可回收内存,降低需要搬回的换出页数量
|
||||||
|
sync
|
||||||
|
echo 3 > /proc/sys/vm/drop_caches 2>/dev/null || true
|
||||||
|
|
||||||
|
# 工具函数:创建指定大小(MB)的交换文件并启用
|
||||||
|
make_swapfile() {
|
||||||
|
local path="$1" size="$2"
|
||||||
|
rm -f "$path" 2>/dev/null || true
|
||||||
|
# 优先使用 fallocate(更快),失败则退回 dd
|
||||||
|
if ! fallocate -l "${size}M" "$path" 2>/dev/null; then
|
||||||
|
dd if=/dev/zero of="$path" bs=1M count="$size" status=progress
|
||||||
|
fi
|
||||||
|
chmod 600 "$path"
|
||||||
|
mkswap "$path" >/dev/null
|
||||||
|
swapon "$path"
|
||||||
|
}
|
||||||
|
|
||||||
|
if swapon --show=NAME --noheadings 2>/dev/null | grep -qx "/swapfile"; then
|
||||||
|
# /swapfile 正在使用:先用临时缓冲文件接管换出页,再安全重建 /swapfile
|
||||||
|
log "${YELLOW}检测到 /swapfile 正在使用,建立临时缓冲交换以安全重建...${NC}"
|
||||||
|
make_swapfile /swapfile.tmp "$SWAP_SIZE"
|
||||||
|
|
||||||
|
# 关闭旧的 /swapfile(换出页会迁移到 /swapfile.tmp,从而避免 OOM)
|
||||||
|
log "${YELLOW}关闭旧的 /swapfile...${NC}"
|
||||||
|
if swapoff /swapfile; then
|
||||||
|
rm -f /swapfile
|
||||||
|
else
|
||||||
|
log "${RED}关闭旧 /swapfile 失败,已保留临时缓冲交换,请手动检查${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 关闭其它可能存在的旧交换设备/文件
|
||||||
|
for DEVICE in $(swapon --show=NAME --noheadings 2>/dev/null); do
|
||||||
|
[ "$DEVICE" = "/swapfile.tmp" ] && continue
|
||||||
|
log "${YELLOW}关闭其它交换空间: $DEVICE${NC}"
|
||||||
|
if swapoff "$DEVICE" 2>/dev/null; then
|
||||||
|
[ -f "$DEVICE" ] && rm -f "$DEVICE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 创建最终的 /swapfile(临时缓冲里的换出页可迁移到这里)
|
||||||
|
log "${GREEN}创建${SWAP_SIZE}MB大小的交换文件 /swapfile...${NC}"
|
||||||
|
make_swapfile /swapfile "$SWAP_SIZE"
|
||||||
|
|
||||||
|
# 关闭并删除临时缓冲(其页面会迁移到新的 /swapfile,仍不会 OOM)
|
||||||
|
log "${YELLOW}清理临时缓冲交换...${NC}"
|
||||||
|
swapoff /swapfile.tmp 2>/dev/null || true
|
||||||
|
rm -f /swapfile.tmp
|
||||||
|
else
|
||||||
|
# /swapfile 未使用:先创建新 /swapfile,再关闭其它旧交换
|
||||||
|
log "${GREEN}创建${SWAP_SIZE}MB大小的交换文件 /swapfile...${NC}"
|
||||||
|
make_swapfile /swapfile "$SWAP_SIZE"
|
||||||
|
for DEVICE in $(swapon --show=NAME --noheadings 2>/dev/null); do
|
||||||
|
[ "$DEVICE" = "/swapfile" ] && continue
|
||||||
|
log "${YELLOW}关闭其它交换空间: $DEVICE${NC}"
|
||||||
|
if swapoff "$DEVICE" 2>/dev/null; then
|
||||||
|
[ -f "$DEVICE" ] && rm -f "$DEVICE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 从fstab移除旧的 swap 条目(匹配 swap 文件系统类型或 /swapfile 路径),再写入新条目
|
||||||
|
sed -i '/[[:space:]]swap[[:space:]]/d; /swapfile/d' /etc/fstab
|
||||||
if ! grep -q "/swapfile" /etc/fstab; then
|
if ! grep -q "/swapfile" /etc/fstab; then
|
||||||
echo "/swapfile swap swap defaults 0 0" >> /etc/fstab
|
echo "/swapfile swap swap defaults 0 0" >> /etc/fstab
|
||||||
log "${GREEN}已添加到fstab,开机将自动挂载${NC}"
|
log "${GREEN}已添加到fstab,开机将自动挂载${NC}"
|
||||||
|
|||||||
Reference in New Issue
Block a user