卸载路径下的所有嵌套目录

卸载路径下的所有嵌套目录

让我们考虑一下这些条件:

  • 有多个嵌套的安装了很多文件夹/文件/mnt
    sdb      8:16   0   300G  0 disk
    ├─sdb1   8:17   0   256M  0 part /mnt/1/1
    ├─sdb2   8:18   0 199.7G  0 part /mnt/2
    └─sdb3   8:19   0   100G  0 part /mnt/3/1/2
    
  • 假设我不知道/dev/sdb安装了哪些设备(例如 )/mnt(因为我想在无人值守的脚本中使用它)。
  • 挂载目录的路径也是未知的。
  • not mounted错误不应停止进程

这是我尝试过的结果说明:

$ umount --all-targets --recursive /mnt; lsblk /dev/sdb
umount: /mnt: not mounted
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sdb      8:16   0   300G  0 disk
├─sdb1   8:17   0   256M  0 part /mnt/1/1
├─sdb2   8:18   0 199.7G  0 part /mnt/2
└─sdb3   8:19   0   100G  0 part /mnt/3/1/2

$ umount --all-targets --recursive /mnt/*/**; lsblk /dev/sdb
umount: /mnt/2/boot: not mounted
umount: /mnt/2/ostree: not mounted
umount: /mnt/3/1: not mounted
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sdb      8:16   0   300G  0 disk
├─sdb1   8:17   0   256M  0 part
├─sdb2   8:18   0 199.7G  0 part /mnt/2
└─sdb3   8:19   0   100G  0 part /mnt/3/1/2

$ umount --all-targets --recursive /mnt/*?; lsblk /dev/sdb
umount: /mnt/1: not mounted
umount: /mnt/3: not mounted
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sdb      8:16   0   300G  0 disk
├─sdb1   8:17   0   256M  0 part /mnt/1/1
├─sdb2   8:18   0 199.7G  0 part
└─sdb3   8:19   0   100G  0 part /mnt/3/1/2

$ umount --all-targets --recursive /mnt/*/**?; lsblk /dev/sdb
umount: /mnt/2/boot: not mounted
umount: /mnt/2/ostree: not mounted
umount: /mnt/3/1: not mounted
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sdb      8:16   0   300G  0 disk
├─sdb1   8:17   0   256M  0 part
├─sdb2   8:18   0 199.7G  0 part /mnt/2
└─sdb3   8:19   0   100G  0 part /mnt/3/1/2

有没有什么好的方法可以在不安装任何额外软件包的情况下做到这一点?

答案1

请告诉我是否有更好的方法来做到这一点!

我发布我的发现来帮助其他人:

  1. 出于好奇,我发现这非常有用,因为它不会抛出not mounted错误,但这仅在设备名称已知且每个分区/磁盘部分没有或有 1 个挂载点时才有效(作为参考,添加--all-targets可能会导致未安装错误,并且用 抑制它|| true是一种不好的做法):

    $ umount /dev/sdb?*
    

    相反,为了处理每个分区/磁盘部分的多个挂载点,我想出了这个来自动卸载磁盘的所有挂载点:

    $ lsblk --noheadings --output MOUNTPOINTS /dev/sdb | xargs -r umount
    
  2. 然而,为了解决我原来的问题中的问题,我想出了这个:

    $ umount $(df -h --output=target | grep /mnt)
    

    事实证明,它只有在安装了某些东西时才有用,这是一个改进的版本,它提供了更准确的匹配,并且仅在安装时才卸载:

    $ df -h --output=target | grep -w /mnt | xargs -r umount
    

    这可以进一步调整。如果磁盘安装在多个位置,以前的版本无法列出所有目录。用不同的方法修复它:

    $ lsblk --output MOUNTPOINTS | grep -w /mnt | xargs -r umount
    

答案2

我会用:

cd /mnt
find -type d -exec mountpoint {} \;|grep -v not|cut -d" " -f1|tac|xargs umount

这将卸载 /mnt 下的所有已安装目录。我想这就是你想做的。这不需要知道安装点的设备或路径(/mnt 下面的安装点除外)。它仅在已安装的安装点上运行。

这种方式是寻找挂载点,而不是尝试猜测设备并检查它们是否挂载在 /mnt 下。它将处理循环挂载和网络挂载以及使用磁盘设备的挂载。

find -type d 搜索目录以提高效率(尽管文件和目录可能可以绑定安装,但不确定)。 tac 会颠倒顺序,因此我们首先卸载层次结构中更下方的挂载点。

答案3

从存储供应商那里得到这个,它可以在 bash 中运行

MOUNTDIR=/mnt

# Sort MOUNTDIR to unmount nested filesystems first
if [[ "$OS" == "AIX" ]]
then
  KEYS=$(
  for KEY in ${!MOUNTDIR[@]}
  do
    echo "${MOUNTDIR[$KEY]}:::$KEY"
  done | sort | awk -F::: '{print $2}'
  )
else
  KEYS=$(
  for KEY in ${!MOUNTDIR[@]}
  do
    echo "${MOUNTDIR[$KEY]}:::$KEY"
  done | sort -r | awk -F::: '{print $2}'
  )
fi

for OLDLV in $KEYS
do
  if [[ "$OS" == "AIX" ]]
  then
    echo "/usr/sbin/fuser -k ${MOUNTDIR[$OLDLV]}"
    if [[ -v COMMIT ]]; then /usr/sbin/fuser -k ${MOUNTDIR[$OLDLV]}; fi
    echo "umount ${MOUNTDIR[$OLDLV]}"
    if [[ -v COMMIT ]]; then umount ${MOUNTDIR[$OLDLV]}; fi
  else
    echo "fuser -kmMs ${MOUNTDIR[$OLDLV]}"
    if [[ -v COMMIT ]]; then fuser -kmMs ${MOUNTDIR[$OLDLV]}; fi
    echo "umount ${MOUNTDIR[$OLDLV]}"
    if [[ -v COMMIT ]]; then umount ${MOUNTDIR[$OLDLV]}; fi
  fi
done

相关内容