题 检查卷是否在Bash脚本中安装的最佳方法是什么?


检查卷是否在Bash脚本中安装的最佳方法是什么?

我真正喜欢的是一种我可以这样使用的方法:

if <something is mounted at /mnt/foo> 
then
   <Do some stuff>
else
   <Do some different stuff>
fi

90
2017-08-05 20:16




我本来就要写一个脚本来自己做。我的第一个想法是从/ etc / mtab中获取信息但我没有翻阅我的bash书籍,看看是否有更直接的方法。 - 3dinfluence
@ 3dinfluence - 是的,我很久以前就知道了,但是 /etc/mtab, /proc/mounts 与...有关 /proc/self/mounts。 (至少在Fedora 20上) - Wilf


答案:


避免使用 /etc/mtab 因为它可能不一致。

避免管道 mount 因为它不必那么复杂。

只是:

if grep -qs '/mnt/foo ' /proc/mounts; then
    echo "It's mounted."
else
    echo "It's not mounted."
fi

(之后的空间) /mnt/foo 是避免匹配,例如 /mnt/foo-bar。)


103
2017-08-05 20:27



更不用说,如果mountpoint被楔入,对mount的调用可能会挂起。 - Chad Huneycutt
适用于linux,不适用于freebsd或solaris。 - chris
这是真的,克里斯。虽然这个问题被标记为linux。 - Dan Carley
我想这是一个哲学问题 - 我们是否应该尝试在可能的情况下使事物变得可移植,或者我们应该假设所有世界运行的Windows / Linux并相应地采取行动? - chris
实际上,你应该测试'/ mnt / foo',即。如果您安装了一个名为例如的卷,则可能会出现误报。 'fooks'。我刚刚遇到了两个挂载点,'lmde'和'lmde-home'。 - marlar


if mountpoint -q /mnt/foo 
then
   echo "mounted"
else
   echo "not mounted"
fi

要么

mountpoint -q /mnt/foo && echo "mounted" || echo "not mounted"

53
2018-01-04 08:33



仅供参考: mountpoint 源自Ubuntu / Debian中的“initscripts”包。 - blueyed
没有为我工作 - :-( - Wilf
这就是我的Vagrant所依赖的电话。 - dhill
这个问题 mountpoint 事实上,它是否安装了安装点,但是如果安装了设备则不会。如果设备通过了 -x 选项它会告诉您主要/次要设备编号,但不会显示它是否已安装。 - vegatripy


像这样的脚本永远不可移植。 unix中的一个肮脏的秘密就是只有内核知道哪些文件系统在哪里,而且缺少/ proc(不可移植)这样的东西它永远不会给你一个直接的答案。

我通常使用df来发现子目录的挂载点,以及它所在的文件系统。

例如(需要像灰/ AT&T ksh / bash /等posix shell)

case $(df  $mount)
in
  $(df  /)) echo $mount is not mounted ;;
  *) echo $mount has a non-root filesystem mounted on it ;;
esac

Kinda告诉您有用的信息。


6
2017-08-05 20:32



问题是标记为linux,所以也许它不必是可移植的 - Rory


以下是我在我的一个rsync备份cron-jobs中使用的内容。它会检查/ backup是否已挂载,如果不挂载则尝试挂载(由于驱动器位于热插拔托架中,可能无法安装,因此可能无法安装)

注意:以下仅适用于linux,因为它greps / proc / mounts - 一个更便携的版本将运行'mount | grep / backup',如马修的答案..

  如果! grep -q / backup / proc / mounts;然后
    如果!装载/备份;然后
      回声“失败”
      1号出口
    科幻
  科幻
  回声“成功了”。
  #在这里做点什么

6
2017-08-05 20:39



作为一个良好的理智检查替代品。 - Dan Carley
据推测,这种方法遇到了与Matthew Bloch的答案相同的问题。 - mwfearnley
是的,除了“Eliptical view”提到的文件名称空间问题(这会影响整行,而不仅仅是提取的字段)。除非你以某种方式忘记引用参数是你可以做的事情,否则子字符串问题不是什么大问题。例如 grep -q ' /backup ' /proc/mounts 要么 mount | grep -q ' /backup '。或者,如果grep不支持,则重定向到/ dev / null -q (哪一个 是 在这些天grep的POSIX规范中)。 - cas


findmnt -rno SOURCE,TARGET "$1" 避免其他答案中的所有问题。只需一个命令即可完成工作。


其他方法有这些缺点:

  • 解析 安装白色空间有问题。它的手册页现在说:

..维护列表模式仅用于向后兼容。

用于更强大和可定制的输出使用 findmnt(8),特别是在你的脚本中。


  • grep -q 和 grep -s 是一个额外的不必要的步骤,并不是在任
  • /proc/\* 到处都不受支持。
  • mountinfo 基于/ proc / ..
  • cut -f3 -d' ' 弄乱路径名中的空格

功能:

#These functions return exit codes: 0 = found, 1 = not found

isMounted    () { findmnt -rno SOURCE,TARGET "$1" >/dev/null;} #path or device
isDevMounted () { findmnt -rno SOURCE        "$1" >/dev/null;} #device only
isPathMounted() { findmnt -rno        TARGET "$1" >/dev/null;} #path   only

#where: -r = --raw, -n = --noheadings, -o = --output

用法示例:

if isPathMounted "/mnt/foo bar";      #Spaces in path names are ok.
   then echo "path is mounted"
   else echo "path is not mounted"
fi

if isDevMounted "/dev/sdb4"; 
   then echo "device is mounted"
   else echo "device is not mounted"
fi

#Universal:
if isMounted "/mnt/foo bar"; 
   then echo "device is mounted"
   else echo "device is not mounted"
fi

if isMounted "/dev/sdb4";
   then echo "device is mounted"
   else echo "device is not mounted"
fi

5
2018-03-15 16:42



无论如何,对于Linux而言,这确实是最好的方法。我见过了 findmnt(8) 命令,但我从来没有真正玩过它。坦率地说,如果我要更新我的一些脚本,这些脚本在Linux机器上(或者命令可用的地方)执行此类事情(或者创建新的脚本),这就是我要做的。 - Pryftan


因为为了挂载,你需要在那里有一个目录,它被挂载,我的策略总是创建一个伪造的文件,其中包含一个永远不会被使用的奇怪文件名,只是检查它是否存在。如果文件在那里,那么那个地方没有安装任何东西......

我不认为这适用于安装网络驱动器或类似的东西。我把它用于闪存驱动器。


2
2017-08-05 20:36





比较设备号码怎么样?我只是想想最多 深奥 办法..

#!/bin/bash
if [[ $(stat -c "%d" /mnt) -ne $(stat -c "%d" /mnt/foo) ]]; then
    echo "Somethin mounted there I reckon"
fi

我的逻辑中有一个缺陷......

作为一个功能:

#!/usr/bin/bash
function somethingMounted {
        mountpoint="$1"
        if ! device1=$(stat -c "%d" $mountpoint); then
                echo "Error on stat of mount point, maybe file doesn't exist?" 1>&2
                return 1
        fi
        if ! device2=$(stat -c "%d" $mountpoint/..); then
                echo "Error on stat one level up from mount point, maybe file doesn't exist?" 1>&2
                return 1
        fi

        if [[ $device1 -ne $device2 ]]; then
                #echo "Somethin mounted there I reckon"
                return 0
        else
                #echo "Nothin mounted it seems"
                return 1
        fi
}

if somethingMounted /tmp; then
        echo "Yup"
fi

回声错误消息可能是多余的,因为stat也会显示错误。


2
2017-08-05 20:57



实际上,可能必须首先检查每个调用的stat的退出状态,以确保文件在那里...不像我想的那样新颖:-( - Kyle Brandt♦


这些都不满足给定目录是另一个安装点内的子目录的用例。例如,您可能拥有/ thing是对主机的NFS挂载:/ real_thing。在/ proc / mounts / etc / mtab或'mount'上使用grep将无法正常工作,因为您将查找不存在的挂载点。例如,/ thing / thingy不是挂载点,但是/ thing挂载在host:/ real_thing上。这里投票的最佳答案实际上并非“确定目录/ volumne是否已安装的最佳方法”。我赞成使用'df -P'(-P POSIX标准模式)作为更清洁的策略:

dev=`df -P /thing/thingy | awk 'BEGIN {e=1} $NF ~ /^\/.+/ { e=0 ; print $1 ; exit } END { exit e }'` && {
    echo "Mounted via: $dev"
} || {
    echo "Not mounted"
}

运行它的输出将是:

Mounted via: host:/real_thing

如果你想知道真正的挂载点是什么,没问题:

mp=`df -P /thing/thingy | awk 'BEGIN {e=1} $NF ~ /^\/.+/ { e=0 ; print $NF ; exit } END { exit e }'` && {
    echo "Mounted on: $mp"
} || {
    echo "Not mounted"
}

该命令的输出将是:

Mounted on: /thing

如果您尝试创建某种chroot,通过某些任意目录或文件列表在chroot内镜像chroot之外的挂载点,这一切都非常有用。


1
2017-10-24 13:59