160

What's the best way to check if a volume is mounted in a Bash script?

What I'd really like is a method that I can use like this:

if <something is mounted at /mnt/foo> 
then
   <Do some stuff>
else
   <Do some different stuff>
fi
Mark Biek
  • 1,927
  • 2
  • 14
  • 12
  • I was just about to write a script to do this myself. My first thought is to get info out of /etc/mtab But I haven't thumbed through my bash books yet to see if there's a more direct way. – 3dinfluence Aug 05 '09 at 20:23
  • @3dinfluence - yes I know this from a long time ago, but `/etc/mtab`, `/proc/mounts` are linked to `/proc/self/mounts`. *(atleast on Fedora 20 it is)* – Wilf Jan 16 '14 at 20:24
  • Similar questions are on **Server Fault**, [Stack Overflow](//stackoverflow.com/q/9422461) and [Unix & Linux Stack Exchange](//unix.stackexchange.com/q/38870). – Sasha Aug 11 '19 at 22:05
  • This command gave the best overview, IMHO: `fdisk -l` – Avatar Mar 30 '21 at 05:07

18 Answers18

188

Avoid using /etc/mtab because it may be inconsistent.

Avoid piping mount because it needn't be that complicated.

Simply:

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

(The space after the /mnt/foo is to avoid matching e.g. /mnt/foo-bar.)

Torsten Bronger
  • 276
  • 1
  • 2
  • 12
Dan Carley
  • 25,617
  • 5
  • 53
  • 70
  • 12
    Not to mention, a call to mount can hang if the mountpoint is wedged. – Chad Huneycutt Aug 05 '09 at 20:32
  • 11
    Good for linux, not for freebsd or solaris. – chris Aug 05 '09 at 20:34
  • 6
    This is true, chris. Although the question was tagged linux. – Dan Carley Aug 05 '09 at 20:38
  • Yes, we can assume linux for my purposes :) – Mark Biek Aug 05 '09 at 20:42
  • 4
    I guess this is a philosophical question -- should we attempt to make things portable if possible or should we just assume that all the world's running windows/linux and act accordingly? – chris Aug 05 '09 at 20:47
  • I think it depends on what you're doing. I'm writing a simple one-off script for non-production use, so I'm not going to spend a lot of time on edge cases :). – Mark Biek Aug 05 '09 at 20:51
  • 1
    But what's the purpose of this site, to answer questions as specifically as possible or to provide useful, general solutions? Meta meta meta, but still. – chris Aug 05 '09 at 20:54
  • I'd say provide the best solution to the task at hand. I would rather using something more efficient if there wasn't a portability requirement. Saying that, I'd be interested if there was an as efficient non `mount` and pipe solution for sol/bsd. I've been spoilt by Python's `os.path.ismount()` recenty. – Dan Carley Aug 05 '09 at 20:59
  • @danc -- useless use of test -- you can rewrite this as if grep -qs mnt.foo /proc/mounts ; then echo "it's mounted" ; else echo it is not mounted ; fi ; : no need for the $? bodge – chris Aug 05 '09 at 21:01
  • 2
    Or skip the if/else and use: `grep -qs '/mnt/foo' /proc/mounts && echo "It's mounted." || echo "It's not mounted".` – mpbloch Aug 05 '09 at 21:07
  • Not as useful/tidy as part of a larger script of actions though. – Dan Carley Aug 05 '09 at 21:10
  • 2
    re: linux vs non linux, the question was tagged linux. So it's OK to assume Linux. Otherwise it makes as much sense as giving a windows answer to a linux problem. – Amandasaurus Aug 10 '09 at 15:58
  • 25
    Actually, you should test for '/mnt/foo ', ie. with a space or you might get a false positive if you had mounted a volume named eg. 'fooks'. I just got that issue with two mount points, 'lmde' and 'lmde-home'. – marlar Aug 12 '11 at 20:21
  • Hmmm, `cat /proc/mounts` lists a number of entries for an external hard drive even though the drive has been ejected. Probably I didn't 'eject' or unmount the drive properly. – EoghanM Mar 04 '12 at 10:41
  • 3
    Possibly worth mentioning: if you use /proc/mounts at a lower level than a shell script (say, parsing with Perl or Python), you must remember that [`/proc/mounts` is only atomic within a single call to `read()`](http://stackoverflow.com/a/5880485/265575) -- so be sure to read the entire file and then parse it, rather than relying on parsing line-by-line from the file handle itself. – Justin ᚅᚔᚈᚄᚒᚔ Oct 24 '12 at 14:10
  • @DanCarley - Don't use `'` in the `echo` bits, it has problems with that *(in terminal atleast)* – Wilf Jan 16 '14 at 20:30
  • `grep '^/mnt/foo\s'` is what you're really searching for. – Quolonel Questions Mar 11 '15 at 11:23
  • 1
    @QuolonelQuestions No. Neither does `/proc/mounts` start with the mount name, nor is `\s` proper grep syntax. – Torsten Bronger Apr 23 '18 at 05:06
  • By the way, if anyone had the same question as me `-qs` does the following: `q` = don't print the "found" lines, simply return an exit code 0 if lines were found. 1 otherwise. `s` = don't print other error messages (eg if some location was inaccessible) – user3728501 Apr 17 '19 at 00:19
  • I have tried this and for me it only works if I dont use `-q` in my if statement, when I use `-q` it always triggers the failure else block. This is on ubuntu. – berimbolo Jul 03 '19 at 14:15
  • Same here. grep manpage says `Exit immediately with zero status if any match is found`. Shouldn't the conditions be swapped? – Joe Feb 12 '20 at 06:34
  • Found it: https://stackoverflow.com/questions/2933843/why-0-is-true-but-false-is-1-in-the-shell – Joe Feb 12 '20 at 17:47
  • Though it's unlikely to be an issue with anything but bind mounts (due to things being mounted `nodev`), this grep expression can match devices with the name of the mountpoint. `awk '{ print $2, $0 }' /proc/mounts | grep '^/mnt/foo '` greps only the mountpoint column, but breaks if there is a space anywhere in a device or mount path: WARNING: /proc/mounts uses space as a delimiter and does not escape spaces in device paths or mount paths. – Wes Turner Sep 23 '20 at 04:39
  • CORRECTION: `/proc/mounts` *does* escape spaces (as `\040`), but `$ mount` does not. – Wes Turner Sep 23 '20 at 04:59
  • AND: bind mount source paths actually aren't listed in `/proc/mounts` or `$ mount`, so it's less likely that this grep expression would match a devicename that ends with the mountpoint pattern. – Wes Turner Sep 23 '20 at 05:05
  • Any solution for MacOS? – a06e Sep 20 '22 at 21:52
102
if mountpoint -q /mnt/foo 
then
   echo "mounted"
else
   echo "not mounted"
fi

or

mountpoint -q /mnt/foo && echo "mounted" || echo "not mounted"
Zaptac
  • 1,037
  • 1
  • 7
  • 2
53

findmnt -rno SOURCE,TARGET "$1" avoids all the problems in the other answers. It cleanly does the job with just one command.


Other approaches have these downsides:

  • grep -q and grep -s are an extra unnecessary step and aren't supported everywhere.
  • /proc/\* isn't supported everywhere. (mountpoint is also based on proc).
  • mountinfo is based on /proc/..
  • cut -f3 -d' ' messes up spaces in path names
  • Parsing mount's white space is problematic. It's man page now says:

.. listing mode is maintained for backward compatibility only.

For more robust and customizable output use findmnt(8), especially in your scripts.


Bash functions:

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

isDevMounted () { findmnt --source "$1" >/dev/null;} #device only
isPathMounted() { findmnt --target "$1" >/dev/null;} #path   only
isMounted    () { findmnt          "$1" >/dev/null;} #device or path

#Usage examples:

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

if isPathMounted "/mnt/C";
   then echo   "path is mounted"
   else echo   "path is not mounted"
fi

#Universal (device OR path):
if isMounted     "/dev/sda10";
   then echo "device is mounted"
   else echo "device is not mounted"
fi

if isMounted     "/mnt/C";
   then echo   "path is mounted"
   else echo   "path is not mounted"
fi
Elliptical view
  • 782
  • 6
  • 9
  • 1
    For Linux specific anyway this is really the best approach. I have seen the *`findmnt(8)`* command but I never really played with it. Frankly if I were to update some of my scripts that do this type of thing (or make new ones) on a Linux box (or where the command is available) this is what I'd do. – Pryftan Apr 14 '18 at 17:49
  • 2
    Note that for encfs, `findmnt` has to be supplied with the parameter `--source encfs`, otherwise it will always consider the directory to be mounted because it falls back to the parent mount. – Burkart Jun 16 '19 at 11:03
  • This is also better than the `grep` solution because if a mount path is weird, you can get false positives: e.g. if I mount `/dev/mmcblk0p1` on `~/mnt/dev/sda1`, I could incorrectly thing that `/dev/sda1` is mounted by the command `mount | grep '/dev/sda1'`. I can't get a false positive using `findmnt`. Good answer! – Cody Piersall Oct 15 '19 at 14:06
  • Why is the `-rno` stuff needed here, if all the output is directed to `dev/null` anyway? – MichaelK Dec 25 '21 at 18:32
  • @MichaelK, right you are. Nice find. Fixed. Thank you. – Elliptical view Dec 26 '21 at 23:20
7

A script like this isn't ever going to be portable. A dirty secret in unix is that only the kernel knows what filesystems are where, and short of things like /proc (not portable) it'll never give you a straight answer.

I typically use df to discover what the mount-point of a subdirectory is, and what filesystem it is in.

For instance (requires posix shell like ash / AT&T ksh / bash / etc)

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

Kinda tells you useful information.

chris
  • 11,944
  • 6
  • 42
  • 51
7

the following is what i use in one of my rsync backup cron-jobs. it checks to see if /backup is mounted, and tries to mount it if it isn't (it may fail because the drive is in a hot-swap bay and may not even be present in the system)

NOTE: the following only works on linux, because it greps /proc/mounts - a more portable version would run 'mount | grep /backup', as in Matthew's answer..

  if ! grep -q /backup /proc/mounts ; then
    if ! mount /backup ; then
      echo "failed"
      exit 1
    fi
  fi
  echo "suceeded."
  # do stuff here
cas
  • 6,783
  • 32
  • 35
  • 3
    Upvoted as a good sanity checking alternative. – Dan Carley Aug 05 '09 at 21:11
  • Presumably this method runs into the same problems as Matthew Bloch's answer. – mwfearnley Apr 09 '18 at 10:06
  • yeah, except for the space-in-filename issue mentioned by "Eliptical view" (this greps the whole line, not just an extracted field). The sub-string issue isn't a big deal unless you somehow forget that quoting arguments is a thing you can do. e.g. `grep -q ' /backup ' /proc/mounts` or `mount | grep -q ' /backup '`. Or redirect to /dev/null if your grep doesn't support `-q` (which *is* in the POSIX spec for grep these days). – cas Apr 09 '18 at 10:48
3

Since in order to mount, you need to have a directory there anyway, that gets mounted over, my strategy was always to create a bogus file with a strange filename that would never be used, and just check for it's existence. If the file was there, then nothing was mounted on that spot...

I don't think this works for mounting network drives or things like that. I used it for flash drives.

Brian Postow
  • 192
  • 1
  • 10
2

How about comparing devices numbers? I was just trying to think of the most esoteric way..

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

There a flaw in my logic with that ...

As a Function:

#!/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

The echo error messages are probably redundant, because stat will display the an error as well.

Kyle Brandt
  • 83,619
  • 74
  • 305
  • 448
  • Actually, would probably have to check the exit status of stat first for each call to make sure the file is there ... not as novel as I thought :-( – Kyle Brandt Aug 05 '09 at 21:08
1

This script will check if the drive is mounted and actually available. It can be written in more compact but I prefer to have it simple like this since I'm not that familiar with Bash. You may want to change the timeout, it is set to 10 sec. in the script.

MNT_DIR=/mnt/foo
df_result=$(timeout 10 df "$MNT_DIR")
[[ $df_result =~ $MNT_DIR ]] 
if [ "$BASH_REMATCH" = "$MNT_DIR" ]
then
    echo "It's available."
else
    echo "It's not available."
fi
Helgi Borg
  • 111
  • 2
1

None of these satisfy the use case where a given directory is a sub directory within another mount point. For example, you might have /thing which is an NFS mount to host:/real_thing. Using grep for this purpose on /proc/mounts /etc/mtab or 'mount' will not work, because you will be looking for a mount point that doesn't exist. For example, /thing/thingy is not a mount point, but /thing is mounted on host:/real_thing. The best answer voted on here is actually NOT "the best way to determine if a directory/volumne is mounted". I'd vote in favour using 'df -P' (-P POSIX standards mode) as a cleaner strategy:

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"
}

The output from running this will be:

Mounted via: host:/real_thing

If you want to know what the real mount point is, no problem:

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"
}

The output from that command will be:

Mounted on: /thing

This is all very useful if you are trying to create some sort of chroot that mirrors mount points outside of the chroot, within the chroot, via some arbitrary directory or file list.

Craig
  • 151
  • 6
1

I think this is useful:

if awk '{print $2}' /proc/mounts | grep -qs "^/backup$"; then
    echo "It's mounted."
else
    echo "It's not mounted."
fi

This gets the second column of /proc/mounts which is mount points.

Then it greps the output. Note the ^ and $, this prevents /backup from matching /mnt/backup or /backup-old etc.

Asclepius
  • 107
  • 5
David
  • 11
  • 3
1

I like the answers that use /proc/mounts, but I don't like doing a simple grep. That can give you false positives. What you really want to know is "do any of the rows have this exact string for field number 2". So, ask that question. (in this case I'm checking /opt)

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

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

if awk -v status=1 '$2 == "/opt" {status=0} END {exit status}' /proc/mounts; then
  echo "yes"
else
  echo "no"
fi
Bruno Bronosky
  • 4,529
  • 3
  • 26
  • 34
0

Although this is a Linux question, why not make it portable when it is easily done?

The manual page of grep says:

Portable shell scripts should avoid both -q and -s and should redirect standard and error output to /dev/null instead.

So I propose the following solution:

if grep /mnt/foo /proc/mounts > /dev/null 2>&1; then
        echo "Mounted"
else
        echo "NOT mounted"
fi
Sean Allred
  • 103
  • 7
fex
  • 9
  • 2
  • 3
    Many UNIX systems do not provide the /proc filesystem – Dima Chubarov Apr 27 '12 at 19:09
  • @DmitriChubarov Indeed. Which makes the concept of portability ironic doesn't it? And maybe it's a more recent update but *`-q`* and *`-s`* are specified by POSIX so there shouldn't be any portability issue with it anyway (now if not before - I've not kept track of what changes happen when). – Pryftan Apr 14 '18 at 17:44
0

grep /etc/mtab for your mount point maybe?

Ophidian
  • 2,178
  • 14
  • 14
0

Does it need to be any more complicated than this?

mount \
    | cut -f 3 -d ' ' \
    | grep -q /mnt/foo \
  && echo "mounted" || echo "not mounted"
Sean Allred
  • 103
  • 7
Matthew Bloch
  • 1,074
  • 8
  • 11
0

This?:

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

From: An Ubuntu forum

RateControl
  • 1,207
  • 9
  • 20
0

Depends what you know about the volume you're checking for.

In the particular case I researched recently, where I was concerned to find if a particular flash drive was mounted, what works most easily is checking for the existence of /dev/disks/by-label/. If the device is plugged in, udev scripts make sure the link exists (and that it is removed when the device is unplugged).

(This is NOT a highly portable answer; it works on many modern Linux distributions, though, and the question was tagged for Linux, and it's a completely different approach from anything so far mentioned so it expands the possibilities.)

0

Create file under your mountpoint like check_mount and then just test if it exists?

if [[ -f /something/check_mount ]]; then
   echo "Mounted
   RC=$?
else
   Echo "Not mounted"
   RC=0
fi
exit $RC
Daniele Santi
  • 2,529
  • 1
  • 25
  • 22
-1

I had to do this in Chef for idempotence since when chef-client would run, the run would fail due to the volume already being mounted. At the time I write this, the Chef mount resource has some kind of bug which wouldn't work with attributes the way I needed, so I mounted the volume using the execute resource instead. Here's how I did it:

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

In case of any confusion, in my attributes file, I have the following:

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

The if not node['docker-server']['mountpoint'] == "none" is a part of a case statement where if the mount point on the server is not specified, the mount point defaults to none.

KLaw
  • 109
  • 2
  • ...and what does this have to do with the original question?!? – Massimo Aug 13 '15 at 21:50
  • The relation of my Chef recipe comment to the original question is that people are increasingly moving toward automation. Therefore, if somebody comes here wondering how to make this work in a Chef recipe, they will have an answer. In life there are two options: 1) Do the bare minimum and make some people happy, and 2) Go the extra mile. Therefore, instead of marking my post down, accept it for what it is: additional information that supports the accepted answer. – KLaw Aug 14 '15 at 22:30
  • The question was about bash scripts, your answer is about Chef scripting. While it could possibly be useful to someone, it still doesn't bear any relevance to the question. – Massimo Aug 15 '15 at 01:08
  • @KLaw **'Therefore, instead of marking my post down, accept it for what it is: additional information that supports the accepted answer.'** I agree and I'm not one to usually down vote (and I haven't here either) but if you have an issue with that type of thing you should maybe add it as an addition to your other points? Might save the other comments. But as for automation that's exactly what bash scripts allow so I fail to see your point. Of course the programmer in me thinks that script above is hideous but that's a language issue more than anything else... – Pryftan Apr 14 '18 at 17:46