检查Bash脚本中是否已挂载卷的最佳方法是什么?

我真正想要的是一种可以像这样使用的方法:

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


评论

我正准备写一个脚本来自己做。我首先想到的是从/ etc / mtab中获取信息,但是我还没有翻阅bash书籍,看看是否还有更直接的方法。

@ 3dinfluence-是的,我很早就知道了,但是/ etc / mtab,/ proc / mounts链接到/ proc / self / mounts。 (至少是Fedora 20)

服务器故障,堆栈溢出以及Unix和Linux堆栈交换也存在类似的问题。

#1 楼

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

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

简单地: />
/mnt/foo后面的空格是为了避免匹配,例如/mnt/foo-bar。)

评论


更不用说,如果安装点被楔入,对挂载的调用可能会挂起。

–乍得·休尼库特(Chad Huneycutt)
09年8月5日在20:32

适用于linux,不适用于freebsd或solaris。

–克里斯
09年8月5日在20:34

克里斯,这是真的。虽然这个问题被标记为linux。

–丹·卡利
09年8月5日在20:38

我猜这是一个哲学问题-我们应该尝试使事情变得可移植,还是应该假设世界上所有正在运行的Windows / Linux并采取相应措施?

–克里斯
09年8月5日在20:47

实际上,您应该测试'/ mnt / foo',即。带有空格,否则如果安装了名为eg的卷,则可能会得到误报。 “傻瓜”。我刚刚遇到了两个挂载点“ lmde”和“ lmde-home”的问题。

–马拉
11年8月12日在20:21

#2 楼

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




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


评论


仅供参考:mountpoint源自Ubuntu / Debian中的“ initscripts”包。

–蓝色
2012-09-25 8:49

没为我工作-:-(

–野生
2014年1月16日20:25

这就是我的流浪者挂断的电话。

–寒意
15年7月28日在13:51

mountpoint的问题在于,它实际上会检查是否已安装安装点,而不是是否已安装设备。如果使用-x选项传递设备,它将告诉您主要/次要设备号,但不会告诉您是否已安装。

–蔬菜
17年8月14日在9:46

@blueyed在Debian Buster中由util-linux软件包提供

– elboulangero
19年6月11日在6:31

#3 楼

findmnt -rno SOURCE,TARGET ""避免了其他答案中的所有问题。它仅用一个命令即可完成这项工作。

其他方法也有以下缺点: 。

并非所有地方都支持grep -q。 (grep -s也基于proc)。

/proc/\*基于/ proc / ..

mountpoint弄乱了路径名中的空格有问题的。现在它的手册页上说:


..列表模式仅用于向后兼容。
要使用更强大和更可定制的输出,请使用findmnt(8),尤其是在脚本中。


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

isMounted    () { findmnt -rno SOURCE,TARGET "" >/dev/null;} #path or device
isDevMounted () { findmnt -rno SOURCE        "" >/dev/null;} #device only
isPathMounted() { findmnt -rno        TARGET "" >/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


评论


无论如何,对于特定于Linux的用户,这实际上是最好的方法。我已经看过findmnt(8)命令,但从未真正使用过它。坦白说,如果我要更新一些在Linux机器上(或命令可用的地方)执行此类操作(或制作新脚本)的脚本,这就是我要做的。

–Pryftan
18年4月14日在17:49



请注意,对于encfs,必须为findmnt提供--source encfs参数,否则它将始终考虑要挂载的目录,因为它会退回到父挂载。

– Burkart
19年6月16日在11:03

这也比grep解决方案更好,因为如果安装路径很奇怪,您可能会得到误报:例如如果在〜/ mnt / dev / sda1上挂载/ dev / mmcblk0p1,我可能会错误地通过命令mount |挂载/ dev / sda1。 grep'/ dev / sda1'。使用findmnt不能得到误报。好答案!

–科迪·皮尔索尔(Cody Piersall)
19-10-15在14:06



#4 楼

像这样的脚本永远不会移植。在Unix中,一个肮脏的秘密是,只有内核知道文件系统在哪里,而缺少/ proc(不可移植)之类的东西,它永远不会给您一个直接的答案。发现子目录的挂载点及其所在的文件系统。

例如(需要posix shell,如ash / AT&T ksh / bash等)

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


Kinda会告诉您有用的信息。

评论


这个问题被标记为linux,所以也许它不一定是可移植的

–罗里
09年8月10日在15:59

#5 楼

以下是我在我的rsync备份cron作业之一中使用的内容。它会检查是否已安装/ backup,并尝试未安装/ backup(它可能会失败,因为驱动器位于热插拔托架中,甚至可能不在系统中)

  if ! grep -q /backup /proc/mounts ; then
    if ! mount /backup ; then
      echo "failed"
      exit 1
    fi
  fi
  echo "suceeded."
  # do stuff here


评论


被推荐为良好的健康检查替代方案。

–丹·卡利
09年8月5日在21:11

据推测,这种方法遇到了与马修·布洛赫(Matthew Bloch)的答案相同的问题。

–mwfearnley
18年4月9日在10:06

是的,除了“椭圆视图”中提到的文件名空间问题(这使整行,而不仅仅是提取的字段)。除非您以某种方式忘记引号是您可以做的事情,否则子字符串问题并不重要。例如grep -q'/ backup'/ proc / mounts或挂载| grep -q'/ backup'。或者,如果您的grep不支持-q,则重定向到/ dev / null(这在最近的grep POSIX规范中)。

–cas
18年4月9日在10:48

#6 楼

由于要进行挂载,无论如何都需要在该目录中挂载一个目录,因此我的策略始终是创建一个伪造的文件,并使用一个永远不会使用的奇怪文件名,然后检查它是否存在。如果文件在那里,那么那个位置什么都不会挂载...

我认为这不适用于挂载网络驱动器或类似的东西。我将其用于闪存驱动器。

#7 楼

如何比较设备编号?我只是想着想出最深奥的方式。.
一个功能:

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


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

评论


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

–凯尔·勃兰特(Kyle Brandt)
09年8月5日在21:08

#8 楼

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

br />
dev=`df -P /thing/thingy | awk 'BEGIN {e=1} $NF ~ /^\/.+/ { e=0 ; print  ; 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"
}


如果您尝试创建某种类型的chroot以在chroot内镜像chroot外部的安装点,那么这将非常有用。 ,通过任意目录或文件列表。

#9 楼

我喜欢使用/proc/mounts的答案,但我不喜欢做简单的grep。那会给你带来误报。您真正想知道的是“对于字段号2,是否有任何行具有此确切的字符串”。所以,问这个问题。 (在这种情况下,我正在检查/opt

 awk -v status=1 ' == "/opt" {status=0} END {exit status}' /proc/mounts

# and you can use it in and if like so:

if awk -v status=1 ' == "/opt" {status=0} END {exit status}' /proc/mounts; then
  echo "yes"
else
  echo "no"
fi
 


#10 楼

我认为这很有用:
if awk '{print }' /proc/mounts | grep -qs "^/backup$"; then
    echo "It's mounted."
else
    echo "It's not mounted."
fi

这将获得/proc/mounts的第二列,即安装点。
然后它抓取输出。注意^和$,这可以防止/ backup与/ mnt / backup或/ backup-old等匹配。

#11 楼

grep / etc / mtab可能是您的挂载点?

评论


mtab可能会过期,或者根本无法通过mount进行更新,例如,当您使用mount -n时,因为/是只读的。

–克里斯
09年8月5日在20:33

我同意,但这似乎是第一个开始寻找的地方。

– phiphidian
09年8月5日在21:30

#12 楼

这是?:

volume="/media/storage"
if mount|grep $volume; then
echo "mounted"
else
echo "not mounted"
if


来自:Ubuntu论坛

#13 楼

尽管这是Linux的问题,但为什么在轻松完成后不使其具有可移植性呢? -q和-s都应该将标准和错误输出重定向到grep


所以我提出了以下解决方案:

if grep /mnt/foo /proc/mounts > /dev/null 2>&1; then
        echo "Mounted"
else
        echo "NOT mounted"
fi

评论


许多UNIX系统不提供/ proc文件系统

– Dmitri Chubarov
2012年4月27日在19:09

@DmitriChubarov确实。是什么使可移植性的概念具有讽刺意味?也许这是一个较新的更新,但是POSIX指定了-q和-s,因此无论如何都不会有任何可移植性问题(现在如果不是以前-我没有跟踪何时发生了什么更改)。

–Pryftan
18年4月14日在17:44

#14 楼

它需要比这更复杂吗?

mount \
    | cut -f 3 -d ' ' \
    | grep -q /mnt/foo \
  && echo "mounted" || echo "not mounted"


评论


grep -q / mnt / foo也将匹配挂载点/ mnt / food和/ not / mnt / foo ... grep -qx / mnt / foo呢?

– rakslice
2012年11月2日,0:51

@rakslice:那是行不通的。 -x仅在整行匹配时才使grep匹配。

– mivk
2012-12-17 22:37

当安装路径的文件名中有空格时,cut -f 3 -d''会失败。

–椭圆视图
18年3月15日在14:07

#15 楼

取决于您对要检查的卷的了解。

在我最近研究的特定案例中,我担心要查找是否安装了特定的闪存驱动器,最容易起作用的是检查/ dev / disks / by-label /的存在。如果已插入设备,则udev脚本将确保链接存在(并且在拔出设备时将其删除)。

(这不是一个高度可移植的答案;但是,它可以在许多现代Linux发行版中使用,并且该问题已针对Linux进行了标记,与迄今为止所提到的任何方法完全不同,因此它扩展了可能性。)

#16 楼

在您的挂载点下创建文件,例如check_mount,然后仅测试文件是否存在?

if [[ -f /something/check_mount ]]; then
   echo "Mounted
   RC=$?
else
   Echo "Not mounted"
   RC=0
fi
exit $RC


#17 楼

我必须在Chef中进行幂等性处理,因为当Chef-client运行时,由于已经安装了卷,因此运行将失败。在我撰写本文时,Chef mount资源存在某种错误,无法按我所需的方式使用属性,因此我改用execute资源安装了该卷。这是我的操作方法:

if not node['docker-server']['mountpoint'] == "none"
  execute "set up mount" do
    user "root"
    command "mount -t ext4 #{node['docker-server']['mountpoint']} #{node['docker-server']['data-dir']}"
    not_if "grep -qs #{node['docker-server']['data-dir']} /proc/mounts"
  end
end


如有任何混淆,请在我的属性文件中输入以下内容:

default['docker-server']['mountpoint'] = "/dev/vdc"
default['docker-server']['data-dir'] = "/data"


if not node['docker-server']['mountpoint'] == "none"case语句的一部分,其中,如果未指定服务器上的安装点,则该安装点默认为none

评论


...这与原始问题有什么关系?!?

–马西莫
15年8月13日在21:50

我的厨师食谱评论与原始问题之间的关系是,人们越来越倾向于自动化。因此,如果有人来这里想知道如何在厨师食谱中完成这项工作,他们将提供答案。在生活中,有两种选择:1)做到最低限度并使一些人快乐,以及2)多加努力。因此,与其将我的帖子标记下来,不如按原样接受:支持已接受答案的其他信息。

– KLaw
2015年8月14日在22:30



问题是关于bash脚本,您的答案是关于Chef脚本。尽管它可能对某人有用,但与该问题没有任何关系。

–马西莫
15年8月15日在1:08

@KLaw'因此,与其将我的帖子记下来,不如按原样接受:支持已接受答案的其他信息。我同意,我也不是通常不赞成投票的人(我也没有在这里投反对票),但是如果您对此类事情有疑问,应该将其添加为其他观点的补充吗?可能保存其他注释。但是对于自动化,这正是bash脚本所允许的,所以我看不到您的意思。当然,我自己的程序员认为上面的脚本很丑陋,但这是语言问题,而不是其他任何问题。

–Pryftan
18年4月14日在17:46