Shell脚本如何清理未挂载的卷

wen 实用脚本 1

本文目录导读:

Shell脚本如何清理未挂载的卷

  1. Linux 系统清理方法
  2. macOS 系统清理方法
  3. Docker 卷清理(特殊场景)
  4. 安全清理脚本(推荐)
  5. 重要注意事项

在Shell脚本中清理未挂载的卷需要谨慎操作,避免误删数据,以下是几种常见文件系统下的清理方法:

Linux 系统清理方法

查看并清理未挂载的卷

#!/bin/bash
# 查看所有磁盘和分区
echo "=== 所有磁盘分区 ==="
lsblk
# 查找未挂载的分区(没有 MOUNTPOINT 的)
echo "=== 未挂载的分区 ==="
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT | grep -v "mounted\|/"
# 或者使用 blkid 查看
echo "=== 使用 blkid 查看 ==="
blkid
# 清理未挂载的卷(危险操作,需要确认)
UMOUNTED=$(lsblk -o NAME,MOUNTPOINT,TYPE | grep -E "disk|part" | awk '{if ($2 == "" && $3 != "lvm" && $3 != "mpath") print $1}')
echo "找到以下未挂载的分区:"
echo "$UMOUNTED"
# 可以选择性清理
for disk in $UMOUNTED; do
    read -p "是否清理 /dev/$disk? (y/n): " confirm
    if [ "$confirm" = "y" ]; then
        echo "正在清理 /dev/$disk..."
        # 使用 dd 命令清空(危险操作)
        # dd if=/dev/zero of=/dev/$disk bs=1M count=100 2>/dev/null
        # 或者只清除分区表
        # wipefs -a /dev/$disk
        echo "已完成"
    fi
done

使用 findmnt 更精确地查找

#!/bin/bash
# 获取所有未挂载的分区
get_unmounted() {
    local mounted
    mounted=$(findmnt -D -o SOURCE,TARGET | grep -E "^/" | awk '{print $1}' | sort -u)
    local all_devices
    all_devices=$(lsblk -o NAME,TYPE | grep -E "disk|part" | awk '{print "/dev/"$1}')
    for device in $all_devices; do
        if ! echo "$mounted" | grep -q "$device"; then
            echo "$device"
        fi
    done
}
# 清理未挂载的LVM卷
clean_lvm_unmounted() {
    echo "=== LVM 未挂载卷 ==="
    lvs -o lv_name,lv_path,attr --noheadings 2>/dev/null | while read line; do
        lv_path=$(echo $line | awk '{print $2}')
        lv_attr=$(echo $line | awk '{print $3}')
        # 如果属性不是 'a'(active),说明未挂载
        if [[ $lv_attr != a* ]]; then
            echo "发现未挂载的LVM卷: $lv_path"
            lvchange -ay "$lv_path" 2>/dev/null || true
        fi
    done
}
# 执行清理
clean_unmounted_volumes() {
    echo "警告:此操作将清理(擦除)未挂载的卷"
    echo "执行前请确保:"
    echo "1. 已备份重要数据"
    echo "2. 已确认这些卷确实不需要"
    echo ""
    read -p "是否继续? (yes/no): " confirm
    if [ "$confirm" != "yes" ]; then
        echo "操作已取消"
        exit 1
    fi
    unmounted_devices=$(get_unmounted)
    if [ -z "$unmounted_devices" ]; then
        echo "没有找到未挂载的设备"
        exit 0
    fi
    echo "以下设备将被清理:"
    echo "$unmounted_devices"
    for device in $unmounted_devices; do
        echo "正在清理 $device ..."
        # 使用安全方式清理(只清除分区表标签)
        sudo wipefs -a "$device" 2>/dev/null || echo "跳过 $device (可能正在使用)"
    done
    echo "清理完成"
}
# 主函数
main() {
    echo "=== 系统卷检查工具 ==="
    echo ""
    clean_lvm_unmounted
    echo ""
    clean_unmounted_volumes
}
main

macOS 系统清理方法

#!/bin/bash
# macOS 下清理未挂载的卷
clean_macos_unmounted() {
    # 查看所有磁盘
    echo "=== 所有磁盘 ==="
    diskutil list
    # 查找未挂载的卷
    echo "=== 未挂载的卷 ==="
    diskutil list external internal | grep -E "^/dev"
    # 获取未挂载的卷列表
    unmounted_volumes=$(diskutil list | grep -E "^/dev" | grep -v "mounted" | awk '{print $1}')
    for volume in $unmounted_volumes; do
        echo "发现未挂载的卷: $volume"
        # 安全方式:弹出卷
        diskutil eject "$volume" 2>/dev/null && echo "已弹出 $volume"
        # 或者完全擦除(危险)
        # diskutil eraseDisk JHFS+ "Clean" /dev/diskX
    done
}

Docker 卷清理(特殊场景)

#!/bin/bash
# 清理 Docker 未使用的卷
clean_docker_volumes() {
    echo "=== Docker 卷状态 ==="
    # 查看所有卷
    echo "所有Docker卷:"
    docker volume ls
    # 清理未被使用的卷
    echo "清理未使用的Docker卷..."
    docker volume prune -f
    # 查看清理后的情况
    echo "清理后剩余的卷:"
    docker volume ls
}
# 清理所有未使用的Docker资源
clean_all_docker() {
    echo "清理所有未使用的Docker资源..."
    docker system prune -a --volumes -f
}

安全清理脚本(推荐)

#!/bin/bash
# 安全清理未挂载卷的脚本
set -euo pipefail
# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
# 错误处理
error_exit() {
    log "错误: $1"
    exit 1
}
# 获取未挂载的设备
get_unmounted_devices() {
    local mounted_devices=$(findmnt -D -o SOURCE | grep "^/" | sort -u)
    local all_block_devices=$(lsblk -o NAME,TYPE,MOUNTPOINT | grep -E "disk|part" | grep -v "loop")
    echo "$all_block_devices" | while read line; do
        local device="/dev/$(echo $line | awk '{print $1}')"
        local mountpoint=$(echo $line | awk '{print $3}')
        if [ -z "$mountpoint" ] && [ -b "$device" ]; then
            # 检查是否被挂载到其他地方
            if ! echo "$mounted_devices" | grep -q "$device"; then
                echo "$device"
            fi
        fi
    done
}
# 主清理函数
main_clean() {
    log "开始检查未挂载的卷..."
    local devices=$(get_unmounted_devices)
    if [ -z "$devices" ]; then
        log "没有找到未挂载的设备"
        exit 0
    fi
    log "发现以下未挂载的设备:"
    echo "$devices"
    # 创建备份列表
    local backup_file="/tmp/unmounted_devices_$(date +%Y%m%d_%H%M%S).txt"
    echo "$devices" > "$backup_file"
    log "设备列表已保存到: $backup_file"
    read -p "是否继续清理? (yes/no): " confirm
    if [ "$confirm" != "yes" ]; then
        log "操作已取消"
        exit 0
    fi
    # 逐设备清理
    while read device; do
        if [ -b "$device" ]; then
            log "正在处理 $device ..."
            # 获取设备信息
            local device_info=$(blkid "$device" 2>/dev/null || true)
            if [ -n "$device_info" ]; then
                log "设备信息: $device_info"
            fi
            # 建议操作,默认只做标签清理
            read -p "对 $device 执行完整清理(1)还是仅清理标签(2)? (1/2): " action
            case $action in
                1)
                    log "执行完整清理: $device"
                    # 使用 dd 清理(危险)
                    # dd if=/dev/zero of="$device" bs=1M count=100 2>/dev/null
                    log "警告: 完整清理操作已注释,请手动执行"
                    ;;
                2)
                    log "清除标签信息: $device"
                    wipefs -a "$device" 2>/dev/null && log "标签清除成功" || log "标签清除失败"
                    ;;
                *)
                    log "跳过 $device"
                    ;;
            esac
        fi
    done <<< "$devices"
    log "清理完成"
}
# 执行主函数
main_clean

重要注意事项

  1. 数据安全:清理前务必备份重要数据
  2. 权限要求:操作磁盘需要 root 权限
  3. 确认操作:建议先用 lsblkblkid 查看确认
  4. 测试环境:先在测试环境中验证脚本

这些脚本提供了不同安全级别的清理选项,建议从最安全的选项开始。

抱歉,评论功能暂时关闭!