使用bash来判断给定UUID的驱动器是否已挂载

3
我正在编写一个Bash脚本,旨在判断给定的驱动器是否已连接到系统,并且如果连接了驱动器,则将一些数据(需要离线备份)复制到该驱动器上。我想通过UUID来识别驱动器/分区,这样我就可以编写一个脚本,经常扫描该驱动器是否存在,并在插入时将数据复制到它上面(通过rsync进行复制,因此如果后续运行是I/O廉价的话,我不会特别在意)。我希望这尽可能简单,以便我可以将相关驱动器交给非技术人员,并告诉他们“在此处插入,然后拔出并随身携带”。在mount中似乎找不到任何选项来做到这一点,而在/etc/fstab中搜索也无法告诉我驱动器是否已挂载。如何根据UUID判断是否已挂载驱动器以及其挂载点是什么?
4个回答

3
设备可以通过其符号链接挂载。如果是这种情况,挂载命令将使用其符号链接引用它,但您可能已经有了其实际路径的引用,或者更糟糕的是另一个符号链接。
更糟糕的是,多个块设备文件可以指向单个块设备(!)。这可以使用mknod命令来完成。
我发现精确获取此信息的唯一方法是将/proc/mounts中所有条目的主要和次要编号与您正在查找的UUID的主要和次要编号进行比较。
以下是一个可执行此操作的函数/脚本。
#!/bin/bash

# $1:     should be a drive uuid, such as that reported by blkid
# return: return value of 0 if mounted, 1 if not mounted
function is_mounted_by_uuid() {
    input_path=$(readlink -f /dev/disk/by-uuid/"$1")
    input_maj_min=$(stat -c '%T %t' "$input_path")

    cat /proc/mounts | cut -f-1 -d' ' | while read block_device; do
        if [ -b "$block_device" ]; then
            block_device_real=$(readlink -f "$block_device")
            blkdev_maj_min=$(stat -c '%T %t' "$block_device_real")

            if [ "$input_maj_min" == "$blkdev_maj_min" ]; then
                return 255
            fi
        fi
    done

    if [ $? -eq 255 ]; then
        return 0
    else
        return 1
    fi
}

if is_mounted_by_uuid "$1"; then
    echo $(readlink -f /dev/disk/by-uuid/$1) is mounted
else
    echo $(readlink -f /dev/disk/by-uuid/$1) is not mounted
fi

2

/dev/disk/by-uuid/是附加卷的符号链接集合。它不能告诉你卷是否已经挂载,但是可以告诉你它是否已插入 - 因此可能符合您特定的用例。

$ ls -l /dev/disk/by-uuid/
total 0
lrwxrwxrwx 1 root root 10 Nov 22 10:08 b928a862-6b3c-45a8-82fe-8f1db2863be3 -> ../../dm-0
lrwxrwxrwx 1 root root 10 Dec  8 14:33 e37fab85-9b00-4d9b-b25e-0970d6eaa3fa -> ../../sdg1

$ readlink /dev/disk/by-uuid/b928a862-6b3c-45a8-82fe-8f1db2863be3 
../../dm-0

那能帮上忙吗?

顺便提一下,我去年解决了一个类似但有所不同的问题,并在我的博客http://ww.telent.net/2011/2/上写了文章。 - telent
确实有帮助,谢谢 - 我不知道 readlink 的存在,尽管我知道 /dev/disk/by-uuid,并试图弄清楚如何利用它来帮助。 - Brighid McDonnell
2
这样做不太可行。即使没有挂载,东西也会显示在/dev/disk/by-uuid中。以下是一个演示此问题的测试:truncate --size=2G ext_file; losetup -fv ext_file; mkfs.ext4 /dev/loop0; blkid /dev/loop0; ls /dev/disk/by-uuid/ - Nick Garvey
好观点@NickGarvey,我已经更新了答案。虽然如果OP在备份之间物理断开磁盘,但能够检测它是否已插入可能对他们来说与检查它是否已挂载一样有用。 - telent

2
mount | grep $(readlink -f /dev/disk/by-uuid/$UUID )

1
我发现最好的方法是使用blkid将UUID转换为Unix文件系统上的块设备,例如:
:~# blkid -U '09b8f1ab-8d4b-4c5f-b395-40be09c090b0'
/dev/sdb1

然后在mount命令的输出中搜索它。保留HTML格式,不进行解释。
:~# mount | grep $(blkid -U '09b8f1ab-8d4b-4c5f-b395-40be09c090b0')
/dev/sdb1 on /media/WD_Disk_1 type ext3 (rw,nosuid,nodev,uhelper=udisks)

然后在其中使用grep命令查找所需的挂载点。
grep -qs '/media/WD_Disk_1 '

完整的命令是

:~# mount | grep $(blkid -U '09b8f1ab-8d4b-4c5f-b395-40be09c090b0') | grep '/media/WD_Disk_1 '
/dev/sdb1 on /media/WD_Disk_1 type ext3 (rw,nosuid,nodev,uhelper=udisks)

我将把这个放入一个if语句中,并隐藏输出,用一个漂亮的小信息来代替它 :-).
if mount | grep $(blkid -U '09b8f1ab-8d4b-4c5f-b395-40be09c090b0') | grep '/media/WD_Disk_1 ' > /dev/null 2>&1;
then
    rsync -az --delete /mnt/data/ /media/WD_Disk_1/current_working_data/;
    echo "sync complete"
else
    echo "couldn't find WD_Disk_1 filesystem"
    exit 1
fi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接