一、重装 PVE 时,安装器在扫描硬盘时可能检测到旧的 PVE 元数据(尤其是 LVM/ZFS),安装器在尝试重命名卷组失败时,会导致安装中断。 本文提供完整的清理方案,确保磁盘干净,PVE 安装器不会再触发 `pve-OLD` 重命名。
二、准备两个 U 盘
1. **SystemRescue U 盘** 用 Rufus 或其他写盘工具,将 [SystemRescue ISO](https://www.system-rescue.org/Download/) 写入一个 U 盘。
2. **pve-clean.sh 脚本 U 盘** 在另一台电脑上准备 U 盘,把以下脚本写入 `pve-clean.sh` 文件:
#!/usr/bin/env bash
# pve-clean.sh (改进版)
# 一键彻底清理指定磁盘的 LVM/ZFS/RAID/LUKS/分区表/签名/头尾元数据 等
# 请务必先阅读脚本并确认 TARGET 指向正确磁盘(例如 /dev/sda)
set -euo pipefail
# ---- 默认参数 ----
TARGET="/dev/sda"
DO_SECURE_ERASE=0 # -s 启用(高风险,仅在直连SATA时使用)
DO_HPA_DCO=0 # -H 启用(极高风险)
FORCE=0 # -y 跳过交互式确认
HEAD_TAIL_MB=32 # 抹头尾大小(MiB)
LOGFILE="/tmp/pve-clean.log"
# ---- 帮助 ----
usage() {
cat <<EOF
Usage: $0 [options]
-d/--disk <device> 目标磁盘(默认: /dev/sda)
-s/--secure-erase 启用 ATA Secure Erase(需 hdparm,直连 SATA,危险)
-H/--hpa-dco 尝试恢复 HPA/DCO(极高风险,可能造成不可用)
-y/--yes 跳过确认(危险)
-h/--help 显示此帮助
Example:
$0 -d /dev/sda
$0 -d /dev/sda -y
EOF
exit 1
}
# ---- 日志与退出处理 ----
log() { echo "[$(date '+%F %T')] $*" | tee -a "$LOGFILE"; }
die() { echo "[$(date '+%F %T')] ERROR: $*" | tee -a "$LOGFILE" >&2; exit 1; }
on_exit() {
local rc=$?
if [[ $rc -ne 0 ]]; then
echo "[$(date '+%F %T')] 脚本异常退出, rc=$rc" | tee -a "$LOGFILE"
else
echo "[$(date '+%F %T')] 脚本正常结束" | tee -a "$LOGFILE"
fi
}
trap on_exit EXIT
# ---- 参数解析(更严格:避免 -d 后无参数) ----
if [[ $# -eq 0 ]]; then
# keep defaults
:
fi
while [[ $# -gt 0 ]]; do
case "$1" in
-d|--disk)
if [[ -z "${2-}" || "${2#-}" != "${2}" ]]; then
die "缺少 -d/--disk 参数,或参数看起来像另一个选项:'$2'"
fi
TARGET="$2"; shift 2 ;;
-s|--secure-erase) DO_SECURE_ERASE=1; shift ;;
-H|--hpa-dco) DO_HPA_DCO=1; shift ;;
-y|--yes) FORCE=1; shift ;;
-h|--help) usage ;;
*)
echo "未知参数: $1"
usage ;;
esac
done
# ---- 环境与安全检查 ----
if [[ $(id -u) -ne 0 ]]; then
die "请以 root 身份运行此脚本 (sudo)。"
fi
if [[ ! -b "$TARGET" ]]; then
die "设备不存在或不是块设备: $TARGET"
fi
DEVNAME=$(basename "$TARGET")
log "目标磁盘: $TARGET (device name: $DEVNAME)"
lsblk -d -o NAME,MODEL,SERIAL,SIZE,TRAN "$TARGET" | tee -a "$LOGFILE" || true
# avoid glob expansion producing literal when no match
shopt -s nullglob
# 检查是否为根盘或系统盘(防止误擦除当前运行盘)
root_src=$(findmnt -n -o SOURCE / || true)
if [[ -n "$root_src" ]]; then
# 例如 /dev/mapper/ubuntu--vg-root 或 /dev/sda2
if [[ "$root_src" == "$TARGET" || "$root_src" == "$TARGET"* ]]; then
die "目标磁盘 ($TARGET) 包含当前系统根分区 ($root_src)。为了安全起见,脚本终止。"
fi
fi
# 通过 /proc/cmdline 或者 /etc/fstab 等也可做更多检查(这里保守处理)
# 检查 /dev/disk/by-id 中是否为 USB 桥接
USB_BRIDGE=0
for id in /dev/disk/by-id/* 2>/dev/null; do
if [[ "$(readlink -f "$id")" == "$TARGET" ]]; then
baseid=$(basename "$id")
if [[ "$baseid" == usb-* || "$baseid" == *-usb-* ]]; then
USB_BRIDGE=1
break
fi
fi
done
if [[ $USB_BRIDGE -eq 1 ]]; then
log "注意:检测到该盘通过 USB 桥接 (by-id 包含 usb-),hdparm/secure-erase/blkdiscard 可能无效或危险。"
fi
# 用户确认(非强制模式)
if [[ $FORCE -ne 1 ]]; then
echo ""
echo "!!! 警告:以下操作会彻底清除 $TARGET 上的所有数据(包括 LVM/ZFS/RAID/LUKS/分区表)。"
echo "如果你确定继续,请输入磁盘名 (例如 $DEVNAME) 再按 Enter:"
read -r CONFIRM
if [[ "$CONFIRM" != "$DEVNAME" ]]; then
die "未输入正确磁盘名,已取消。"
fi
fi
log "开始清理流程,记录写入 $LOGFILE"
# ---- 辅助函数 ----
safe_cmd() {
# 运行命令,捕获错误并记录,但不退出脚本(因为 set -e)
# 用法: safe_cmd some command arg ...
if ! "$@" 2>>"$LOGFILE"; then
log "命令失败: $*(见 $LOGFILE 详情)"
return 1
fi
return 0
}
# ---- 1) 基础停用/卸载 ----
log "1) 取消挂载、停用 swap、停用 LVM/MD/ZFS(开始)"
set +e
# 构造设备列表(包含 TARGET 自身和其可能的子设备)
devs=()
devs+=("$TARGET")
# 添加匹配的设备(例如 /dev/sda1 /dev/sda2 /dev/sda-part 等)
for match in "${TARGET}"*; do
# 如果 match 与 TARGET 相同已经包含,nullglob 确保只有真实匹配进入
if [[ -b "$match" && "$match" != "$TARGET" ]]; then
devs+=("$match")
fi
done
# 卸载所有该盘的挂载点(递归)
for part in "${devs[@]}"; do
if [[ -b "$part" ]]; then
mountpoint=$(findmnt -n -o TARGET --source "$part" 2>/dev/null || true)
if [[ -n "$mountpoint" ]]; then
log "尝试 umount -R $part (mounted at $mountpoint)"
umount -R "$part" 2>>"$LOGFILE" || {
log "umount -R 失败,尝试 lazy umount -l $part"
umount -l "$part" 2>>"$LOGFILE" || log "umount 仍失败:$part"
}
fi
fi
done
safe_cmd swapoff -a || true
# 停用所有 LVM 卷组(尽量停掉)
if command -v vgchange >/dev/null 2>&1; then
safe_cmd vgchange -an || true
else
log "vgchange (LVM) 不存在,跳过 vgchange -an"
fi
# 停止 mdadm 阵列(尽量尝试)
if command -v mdadm >/dev/null 2>&1; then
safe_cmd mdadm --stop --scan || true
else
log "mdadm 不存在,跳过 mdadm --stop --scan"
fi
# export zpool
if command -v zpool >/dev/null 2>&1; then
safe_cmd zpool export -a || true
else
log "zpool 不存在,跳过 zpool export -a"
fi
# dmsetup:谨慎处理(仅在有映射且不包含根映射时移除)
if command -v dmsetup >/dev/null 2>&1; then
# 列出映射并检查是否有指向目标的路径
dmsetup ls --target multipath 2>/dev/null || true
# 不直接执行 remove_all(过于激进),仅尝试移除空闲映射
# 如果你确实需要强制移除,请手动运行 dmsetup remove_all
else
log "dmsetup 不存在或不可用,跳过 dmsetup 处理"
fi
set -e
# ---- 2) 清理 LVM(针对该盘的 PV) ----
log "2) 清除 LVM PV/VG/LV 元数据(仅针对与 $TARGET 相关的 PV)"
if command -v pvs >/dev/null 2>&1; then
# 使用分隔符,避免 vg 名含空格导致解析出错
while IFS='|' read -r pv vg; do
pv=${pv:-}
vg=${vg:-}
# 仅处理以 TARGET 前缀匹配的 PV(如 /dev/sda1 或 /dev/mapper/...)
if [[ -n "$pv" && "$pv" == "$TARGET"* ]]; then
log "发现 PV $pv 在 VG $vg:执行 pvremove -ff -y $pv"
pvremove -ff -y "$pv" >>"$LOGFILE" 2>&1 || log "pvremove 失败:$pv"
# 检查该 VG 是否还有 PV
if [[ -n "$vg" ]]; then
if ! pvs --noheadings -o pv_name "$vg" 2>>"$LOGFILE" | grep -q .; then
log "VG $vg 似乎没有 PV,尝试 vgremove -f $vg"
vgremove -f "$vg" >>"$LOGFILE" 2>&1 || log "vgremove 失败:$vg"
fi
fi
fi
done < <(pvs --noheadings --separator '|' -o pv_name,vg_name 2>/dev/null || true)
else
log "系统没有 pvs 工具,跳过 LVM 深度清理"
fi
# ---- 3) 清理 mdadm 超级块(软 RAID) ----
log "3) 清理 mdadm(superblock)(如果有)"
if command -v mdadm >/dev/null 2>&1; then
for dev in "${devs[@]}"; do
if [[ -b "$dev" ]]; then
log "尝试 mdadm --zero-superblock -f $dev"
mdadm --zero-superblock -f "$dev" >>"$LOGFILE" 2>&1 || log "mdadm --zero-superblock 失败: $dev"
fi
done
else
log "mdadm 不存在,跳过 mdadm --zero-superblock"
fi
# ---- 4) 清理 ZFS 标签(头/尾) ----
if command -v zpool >/dev/null 2>&1; then
log "4) 清理 ZFS 标签(如果存在)"
for dev in "${devs[@]}"; do
if [[ -b "$dev" ]]; then
log "尝试 zpool labelclear -f $dev"
zpool labelclear -f "$dev" >>"$LOGFILE" 2>&1 || log "zpool labelclear 失败: $dev"
fi
done
else
log "zpool 不存在,跳过 ZFS labelclear"
fi
# ---- 5) 清理 LUKS (如果存在) ----
if command -v cryptsetup >/dev/null 2>&1; then
log "5) 检测并处理 LUKS (cryptsetup)"
for dev in "${devs[@]}"; do
if [[ -b "$dev" ]]; then
if cryptsetup isLuks "$dev" 2>>"$LOGFILE"; then
log "$dev 被检测为 LUKS,覆盖前 4 MiB 以破坏 header(不可恢复)"
dd if=/dev/zero of="$dev" bs=1M count=4 status=progress conv=fsync 2>>"$LOGFILE" || log "dd 覆盖 LUKS 头失败: $dev"
fi
fi
done
else
log "系统没有 cryptsetup,跳过 LUKS 检测"
fi
# ---- 6) wipefs 清理可见签名 ----
if command -v wipefs >/dev/null 2>&1; then
log "6) wipefs -a 清除可见签名(文件系统/RAID/LVM 等)"
for dev in "${devs[@]}"; do
if [[ -b "$dev" ]]; then
wipefs -a -f "$dev" >>"$LOGFILE" 2>&1 || log "wipefs 失败: $dev"
fi
done
else
log "wipefs 不存在,跳过"
fi
# ---- 7) 清 GPT/MBR(sgdisk -Z/--zap-all) ----
if command -v sgdisk >/dev/null 2>&1; then
log "7) sgdisk --zap-all $TARGET (清 GPT/MBR 主/备表)"
sgdisk --zap-all "$TARGET" >>"$LOGFILE" 2>&1 || log "sgdisk --zap-all 失败"
else
log "sgdisk 不存在,跳过 sgdisk --zap-all"
fi
# ---- 8) multipath 处理 ----
if command -v multipath >/dev/null 2>&1; then
log "8) multipath 检查并删除包含该设备的 map(如果有)"
# 从 multipath -ll 中提取 map 名称(鲁棒处理)
maps=$(multipath -ll 2>/dev/null | awk '/^[^ ]/ {print $1}' || true)
for map in $maps; do
if multipath -ll "$map" 2>>"$LOGFILE" | grep -q "$DEVNAME"; then
log "尝试 multipath -f $map"
multipath -f "$map" >>"$LOGFILE" 2>&1 || log "multipath -f 失败: $map"
fi
done
else
log "multipath 不存在,跳过"
fi
# ---- 9) 抹头(前 HEAD_TAIL_MB MiB) ----
log "9) 抹前 ${HEAD_TAIL_MB}MiB (尝试使用 direct oflag)"
# 尝试使用 oflag=direct,失败后回退
if dd if=/dev/zero of="$TARGET" bs=1M count=$HEAD_TAIL_MB status=progress conv=fsync oflag=direct 2>>"$LOGFILE"; then
log "抹头完成(oflag=direct)"
else
log "oflag=direct 不支持或失败,尝试不使用 oflag"
dd if=/dev/zero of="$TARGET" bs=1M count=$HEAD_TAIL_MB status=progress conv=fsync 2>>"$LOGFILE" || log "抹头失败"
fi
# ---- 10) 抹尾(后 HEAD_TAIL_MB MiB) ----
log "10) 抹尾 ${HEAD_TAIL_MB}MiB(仅在容量允许时)"
if command -v blockdev >/dev/null 2>&1; then
size_bytes=$(blockdev --getsize64 "$TARGET" 2>>"$LOGFILE" || echo 0)
size_mb=$((size_bytes/1024/1024))
if (( size_mb > HEAD_TAIL_MB * 2 )); then
tail_start=$((size_mb - HEAD_TAIL_MB))
log "磁盘总大小: ${size_mb}MiB;从 ${tail_start}MiB 开始写入 ${HEAD_TAIL_MB}MiB"
if dd if=/dev/zero of="$TARGET" bs=1M seek=$tail_start count=$HEAD_TAIL_MB status=progress conv=fsync oflag=direct 2>>"$LOGFILE"; then
log "抹尾完成(oflag=direct)"
else
log "oflag=direct 抹尾失败,尝试不使用 oflag"
dd if=/dev/zero of="$TARGET" bs=1M seek=$tail_start count=$HEAD_TAIL_MB status=progress conv=fsync 2>>"$LOGFILE" || log "抹尾失败"
fi
else
log "磁盘太小 (${size_mb}MiB),跳过尾部抹写"
fi
else
log "blockdev 不存在,无法获取磁盘大小,跳过尾部抹写"
fi
sync
# ---- 11) blkdiscard(如果是 SSD 且支持) ----
if command -v blkdiscard >/dev/null 2>&1; then
if [[ $USB_BRIDGE -eq 0 ]]; then
log "11) 尝试 blkdiscard -v $TARGET(如果设备支持)"
blkdiscard -v "$TARGET" >>"$LOGFILE" 2>&1 || log "blkdiscard 失败或不支持"
else
log "设备通过 USB,跳过 blkdiscard(通常无效或危险)"
fi
else
log "blkdiscard 不存在,跳过"
fi
# ---- 12) 可选:ATA Secure Erase(高风险) ----
if [[ $DO_SECURE_ERASE -eq 1 ]]; then
if [[ $USB_BRIDGE -eq 1 ]]; then
log "检测到 USB 桥接,跳过 ATA Secure Erase(USB 桥通常不支持 ATA 命令)"
elif ! command -v hdparm >/dev/null 2>&1 ; then
log "hdparm 不存在,无法进行 ATA Secure Erase,跳过"
else
log "12) ATA Secure Erase 检查"
# 查询并输出(记录)
hdparm -I "$TARGET" 2>&1 | tee -a "$LOGFILE" || log "hdparm -I 失败"
# 检查是否 frozen(宽松匹配)
if hdparm -I "$TARGET" 2>/dev/null | grep -qi frozen; then
log "磁盘状态显示为 FROZEN,无法直接执行 secure erase。请解除 frozen(例如 BIOS 热插/重启/挂起恢复),脚本不会自动挂起。"
else
# 额外确认(用户交互)
if [[ $FORCE -ne 1 ]]; then
echo ""
echo "警告:你选择了 --secure-erase。这会触发硬件级安全擦除,可能需要较长时间且不可逆。输入 'yes' 确认继续:"
read -r seconf
if [[ "$seconf" != "yes" ]]; then
log "用户未确认 secure erase,跳过"
else
ERASE_PW="pveclean"
log "设置临时口令并尝试执行 --security-erase-enhanced(若不支持则 fallback 到普通)"
hdparm --user-master u --security-set-pass "$ERASE_PW" "$TARGET" >>"$LOGFILE" 2>&1 || log "hdparm 设置口令失败"
if hdparm --user-master u --security-erase-enhanced "$ERASE_PW" "$TARGET" >>"$LOGFILE" 2>&1; then
log "执行 --security-erase-enhanced 成功(请等待完成)"
else
log "--security-erase-enhanced 不支持或失败,尝试 --security-erase"
hdparm --user-master u --security-erase "$ERASE_PW" "$TARGET" >>"$LOGFILE" 2>&1 || log "--security-erase 也失败"
fi
fi
else
log "强制模式(-y)已开启,直接尝试 secure erase(风险自负)"
ERASE_PW="pveclean"
hdparm --user-master u --security-set-pass "$ERASE_PW" "$TARGET" >>"$LOGFILE" 2>&1 || log "hdparm 设置口令失败"
if hdparm --user-master u --security-erase-enhanced "$ERASE_PW" "$TARGET" >>"$LOGFILE" 2>&1; then
log "执行 --security-erase-enhanced 成功"
else
log "--security-erase-enhanced 不支持或失败,尝试 --security-erase"
hdparm --user-master u --security-erase "$ERASE_PW" "$TARGET" >>"$LOGFILE" 2>&1 || log "--security-erase 也失败"
fi
fi
fi
fi
fi
# ---- 13) 可选:HPA/DCO 检查(脚本默认不自动更改) ----
if [[ $DO_HPA_DCO -eq 1 ]]; then
if ! command -v hdparm >/dev/null 2>&1 ; then
log "hdparm 不存在,无法做 HPA/DCO 操作,跳过"
elif [[ $USB_BRIDGE -eq 1 ]]; then
log "设备通过 USB,跳过 HPA/DCO 操作(USB 桥不支持)"
else
log "13) 检查 HPA / DCO(脚本仅显示,不自动修改)"
# hdparm -N 输出解析(尽可能容错)
hdparm_N_out=$(hdparm -N "$TARGET" 2>>"$LOGFILE" || true)
if [[ -n "$hdparm_N_out" ]]; then
# 尝试解析 native 和 current
native=$(echo "$hdparm_N_out" | awk -F'(' '/native/ {print $1}' | grep -o '[0-9]\+' || true)
cur=$(echo "$hdparm_N_out" | awk -F'(' '/current/ {print $1}' | grep -o '[0-9]\+' || true)
log "hdparm -N 输出(摘录): $(echo "$hdparm_N_out" | tr '\n' ' ' | cut -c1-300)"
log "解析结果:native=$native current=$cur"
if [[ -n "$native" && -n "$cur" && "$cur" -lt "$native" ]]; then
log "注意:current < native,表示存在 HPA/DCO,理论上可用 hdparm -N p<native> 恢复(高风险)。脚本不会自动执行恢复。"
fi
else
log "hdparm -N 没有输出,可能不支持对该设备查询"
fi
fi
fi
# ---- 14) 再次 wipefs + sgdisk 兜底 ----
log "14) 最终 wipefs + sgdisk 再次清理(兜底)"
if command -v wipefs >/dev/null 2>&1; then
for dev in "${devs[@]}"; do
if [[ -b "$dev" ]]; then
wipefs -a -f "$dev" >>"$LOGFILE" 2>&1 || log "最终 wipefs 失败: $dev"
fi
done
fi
if command -v sgdisk >/dev/null 2>&1; then
sgdisk -Z "$TARGET" >>"$LOGFILE" 2>&1 || log "sgdisk -Z 失败"
fi
# ---- 15) 刷新内核设备表并自检 ----
log "15) 触发 udev 重新扫描并显示自检结果"
udevadm settle >>"$LOGFILE" 2>&1 || true
partprobe "$TARGET" >>"$LOGFILE" 2>&1 || true
sleep 1
log "lsblk:"
lsblk -o NAME,MODEL,SERIAL,SIZE,TYPE,MOUNTPOINT | tee -a "$LOGFILE" || true
log "wipefs 输出(应为空或仅残留):"
if command -v wipefs >/dev/null 2>&1; then
wipefs "$TARGET" | tee -a "$LOGFILE" || true
fi
log "LVM (pvs/vgs/lvs):"
if command -v pvs >/dev/null 2>&1; then pvs 2>>"$LOGFILE" || true; fi
if command -v vgs >/dev/null 2>&1; then vgs 2>>"$LOGFILE" || true; fi
if command -v lvs >/dev/null 2>&1; then lvs 2>>"$LOGFILE" || true; fi
log "mdadm examine:"
if command -v mdadm >/dev/null 2>&1; then mdadm --examine --scan 2>>"$LOGFILE" || true; fi
if command -v zpool >/dev/null 2>&1; then
log "zpool import -a (仅显示,不自动导入)"
zpool import -a 2>>"$LOGFILE" || true
fi
log "清理完成。请在安装器或系统中重新检测磁盘 ($TARGET)。"
log "提示:如果安装器仍提示旧卷,请重启系统并再次运行此脚本,或检查 BIOS/RAID 控制器是否仍保存盘上元数据。如果还是不行请联系硬盘厂商提供官方工具清理到硬盘固件层数据,或者更换一块硬盘安装PVE,本脚本无法帮助你。"
exit 0
三、启动系统与执行清理
列出所有块设备与分区,找出 U 盘(根据 SIZE / MODEL 区分):
lsblk -o NAME,MAJ:MIN,RM,SIZE,MODEL,VENDOR,MOUNTPOINT
列出 by-id,以便精确识别 U 盘或目标盘:
ls -l /dev/disk/by-id/
假设脚本在 U 盘分区 `/dev/sdb1`(根据 `lsblk` 结果替换):
sudo mkdir -p /mnt/usb
sudo mount /dev/sdb1 /mnt/usb
ls -l /mnt/usb/pve-clean.sh
cd /mnt/usb
赋予执行权限并运行脚本(交互方式,需要输入磁盘名确认):
sudo chmod +x ./pve-clean.sh
sudo ./pve-clean.sh -d /dev/sda
> ⚠️ 替换 `/dev/sda` 为你要清理的目标磁盘!
四、执行后验证
确认没有任何签名:
wipefs /dev/sda
确认没有 LVM PV/VG/LV:
pvs || true
vgs || true
lvs || true
确认 mdadm 没有残余:
mdadm --examine --scan || true
确认 ZFS 不会列出旧池:
zpool import -a 2>/dev/null || true
查看磁盘是否还有分区:
lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT
卸载 U 盘:
sudo umount /mnt/usb
五、清理后自检(在同一 Live 环境或 PVE 安装器 shell)
lsblk -e7 -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT
blkid /dev/sda || true
pvs; vgs; lvs || true
zpool import || true
mdadm --examine --scan || true
六、开始安装 PVE 前的 BIOS/控制器检查
– **SATA 模式**:确保 BIOS 里是 AHCI,不是 “Intel RST/RAID”。
– **硬件 RAID**:如果用过主板/阵列卡的硬件 RAID,请在控制器管理界面删除磁盘组并清除元数据,否则 OS 仍可能在尾部发现控制器格式的超级块(不同厂商有各自工具,需在控制器 BIOS/CLI 里操作)。
– 回到 PVE 安装器,重新扫描磁盘。
七、总结
**普通情况**(单盘、无 RAID/ZFS/LUKS):
sudo wipefs -a /dev/sdX
即可清理残留,PVE 安装器不会触发 `pve-OLD` 重命名。
- **复杂情况**(RAID/ZFS/LUKS、企业存储):
使用完整的 `pve-clean.sh` 脚本彻底清理磁盘头尾、LVM、RAID、ZFS、LUKS 等残留信息。
---
✅ **说明**:
1. 所有命令都在 代码块中,支持 GitHub、Typora、Obsidian、VS Code 等环境自动显示“复制”按钮。
2. 可直接复制此内容保存为 `.md` 文件,开箱即用。
3. 脚本已考虑安全确认、设备去激活、前后元数据清除,适用于企业级残留清理。
---
📌 **建议**:将此文档与 `pve-clean.sh` 一同放入 U 盘,便于现场维护。
