mount那些事

我现在使用的本子是公司发的T430,拿到手之后就把光驱卸了,插了块500G的硬盘。在windows下挂载对用户是透明的,在磁盘管理器里分配一下盘符就可以。而在linux下,做法有许多种,这篇文章就来聊聊linux下mount的那件事儿。

Ubuntu中图形化的mount方式

ubuntu自带的nautilus(相当于windows的资源管理器)中,在Devices这一栏会列出计算机连接的所有磁盘(机器自带的,外接的磁盘,U盘等),且会显示各个设备是否可以mount,或者是否可以umount,点击相应的按钮即可执行相应操作。

以我这块外接的500G硬盘为例(分了两个区),默认的mount信息是这样的:

hweicdl@hweicdl-t430:~$ mount
......
/dev/sdb1 on /media/7EB08052B0801337 type fuseblk (rw,nosuid,nodev,allow_other,default_permissions,blksize=4096)
/dev/sdb2 on /media/FC5CA8BB5CA87256 type fuseblk (rw,nosuid,nodev,allow_other,default_permissions,blksize=4096)

这里的默认的挂载点7EB08052B0801337FC5CA8BB5CA87256是设备的uuid信息:

hweicdl@hweicdl-t430:~$ ll /dev/disk/by-uuid/
total 0
drwxr-xr-x 2 root root 160 Mar  5 17:24 ./
drwxr-xr-x 5 root root 100 Mar  5 17:23 ../
lrwxrwxrwx 1 root root  10 Mar  5 17:24 19498b6a-985e-4a12-9610-e788095532f0 -> ../../sda1
lrwxrwxrwx 1 root root  10 Mar  5 17:24 1d6de973-c3d7-4afa-9b11-412542af3032 -> ../../dm-1
lrwxrwxrwx 1 root root  10 Mar  5 17:24 5ad4fc51-a35e-4de1-89f1-48273b8dc3a7 -> ../../sda2
lrwxrwxrwx 1 root root  10 Mar  5 17:24 7EB08052B0801337 -> ../../sdb1
lrwxrwxrwx 1 root root  10 Mar  5 17:24 ad89e007-ef8d-4076-8447-5eb1c4ebfdb3 -> ../../dm-2
lrwxrwxrwx 1 root root  10 Mar  5 17:24 FC5CA8BB5CA87256 -> ../../sdb2

可以看到这两个设备link向/dev/sdb1/dev/sdb2,跟外挂磁盘相对应。

而这种方式挂载上的文件权限是700:只有当前用户对这个mount的文件系统有权限访问。

hweicdl@hweicdl-t430:~$ ll /media/7EB08052B0801337/
total 132
drwx------ 1 hweicdl hweicdl 16384 Feb 21 14:17 ./
drwxr-xr-x 6 root    root     4096 Mar  5 17:28 ../
drwx------ 1 hweicdl hweicdl  4096 Sep  6 05:13 backup/
drwx------ 1 hweicdl hweicdl     0 Mar 25  2013 demo/
drwx------ 1 hweicdl hweicdl 12288 Nov 22  2012 doc/
drwx------ 1 hweicdl hweicdl 12288 Nov 18 09:39 ebook/
......

手动mount

手动的方式无非就是mount命令本身了,先建两个文件夹/media/sdb1/media/sdb2,然后:

hweicdl@hweicdl-t430:~$ sudo mount /dev/sdb1 /media/sdb1
hweicdl@hweicdl-t430:~$ sudo mount /dev/sdb2 /media/sdb2
hweicdl@hweicdl-t430:~$ mount
......
/dev/sdb1 on /media/sdb1 type fuseblk (rw,nosuid,nodev,allow_other,blksize=4096)
/dev/sdb2 on /media/sdb2 type fuseblk (rw,nosuid,nodev,allow_other,blksize=4096)

这里默认的权限是777:任何用户都可以访问mount上的文件系统。

hweicdl@hweicdl-t430:~$ ll /media/sdb1/
total 132
drwxrwxrwx 1 root root 16384 Feb 21 14:17 ./
drwxr-xr-x 4 root root  4096 Mar  5 20:37 ../
drwxrwxrwx 1 root root  4096 Sep  6 05:13 backup/
drwxrwxrwx 1 root root     0 Mar 25  2013 demo/
drwxrwxrwx 1 root root 12288 Nov 22  2012 doc/
drwxrwxrwx 1 root root 12288 Nov 18 09:39 ebook/

开机自动mount

由于这块外接硬盘每次开机都需要被挂上,若每次都以上述的GUI或命令行方式来挂载就比较烦琐了,而且默认挂载点的名字在使用上也很不方便。mount自动化主要有两种方法:

  1. 将上述的两条mount命令写进/etc/rc.local,在机器启动时它们就被会自动调用
  2. /etc/fstab中添加两条记录
#/dev/sdb1  /media/sdb1  ntfs  nls=iso8859-1,users,umask=000,user  0  0  
#/dev/sdb2  /media/sdb2  ntfs  nls=iso8859-1,users,umask=000,user  0  0

之后mount -a可以立即生效,或者重启系统即可。

一个诡异的无法mount现象

今年过年把电脑带回家,可能是火车上给颠的,外挂的硬盘不能自动挂上了。当时的现象是这样的:

  • 在命令行下,始终报mount fuse: mount failed: Device or resource busy的错
  • 在GUI下,一个盘可以被挂载,另一个始终报错:

    Error mounting: mount exited with exit code 1: helper failed with: Mount is denied because setuid and setgid root ntfs-3g is insecure with theexternal FUSE library.

很诡异的是:出错显示resource busy,但我lsof </dev/sdb2>却不显示任何信息。之后我又把这块硬盘装到一个windows机器上,磁盘状态是正常的。在linux下,我也用fsck检查了,也是正常的。除此之外,还google了很多,均无果。当时真是万念俱灰,准备放弃的时候,在开机的时候看到了启动log:

注意看multipath出错那几行。这里先说一下multipath-tools,在ubuntu 12.04中默认是不带的,我是因为查看一段代码发现了这个玩意,便在本地装了一个想man下看看它究竟是什么。本想着装个multipath-tools是无害的,但在这里,显然在启动时它接管了这块500G的磁盘,把它按照lvm方式来分配使用,这里的/dev/dm-5也就相当于裸的/dev/sdb2,也就是加载不上的那块盘。现在我的机器(fix这个问题后)只有ubuntu默认使用lvm安装时的三块设备符:

hweicdl@hweicdl-t430:~$ ls /dev/dm-*
/dev/dm-0  /dev/dm-1  /dev/dm-2

那么我猜,multipath当时接管这块磁盘分,按照lvm分配的情况是这样的:/dev/sdb内部的lvm符是/dev/dm-3/dev/sdb内部的lvm符是/dev/dm-3/dev/sdb内部的lvm符是/dev/dm-3。然后将它们再创建一个供用户使用的link放在/dev/mapper/下。(但是很可惜的是,我没在当时出问题的时候抓一下这些信息)

看到了这些错误信息,最简单的解决方式就是把multipath-tools卸掉,这个工具其实是用来配置一些厂商的外接设备的,比如IBM,EMC的存储。

现在我的磁盘分配就很清晰了:/dev/sda交给ubuntu安装,默认安装是这样的:

  • 首先分成两个物理磁盘:/dev/sda1/dev/sda2
  • /dev/sda1分配了500M,并mount到/boot上。这个盘跟lvm无关。
  • 剩下的空间都是/dev/sda2,其由lvm接管:
    • 对于lvm来说,在这块盘创建了一个物理卷:/dev/dm-0,有一个link指向它/dev/mapper/lvm_crypt
    • dm-0上,lvm分配了两个卷组:/dev/ubuntu/swap/dev/ubuntu/root。前者在lvm内部的名字叫/dev/dm-1,后者叫/dev/dm-2
  • 对于挂载的这块盘。没有被lvm接管,它们还是跟物理磁盘一一对应:/dev/sdb1/dev/sdb2

所以,回过头看,出现这个诡异的问题应该是multipath-tools这个工具“想”按照lvm的方式来接管它“发现”的磁盘,但由于一些bug没有做的那么完美,导致了这个问题。

苹果设备的mount

通过上面那个问题,倒是让我对mount,lvm的相关知识了解了一些。于是,我想看看苹果设备是如何在ubuntu上加载的,或许可以做些hack的事情?

首先来看看windows上是怎么样的:在每次iPhone连到windows的时候,你会看到它以新盘符的方式出现,并(仅)将其照片文件夹DCIM自动暴露出来。而如果连接到iTunes,有些可以上传文档的应用(例如百度地图)则会将某些文件夹在iTunes里暴露给你。

而在ubuntu上,iPhone是通过gvfsd-afc的协议挂载成gvfs (Gnome virtual file system)。一般说来ubuntu都默认安装了gvfs,所以会自动挂载的。

hweicdl@hweicdl-t430:~$ ls ~/.gvfs
Documents on “HuangWei”的 iPhone  “HuangWei”的 iPhone

这里两个挂载点,前者是以应用的视角呈现出来的(有人给gvfs写了个patch来实现苹果的House Arrest protocol,这里所有的应用都显示出来了)。

乍一看我以为以这些应用里的文件都是可写的,就想着修改一下微信的默认通知声音(目前好像只能越狱才能做到)。

hweicdl@hweicdl-t430:~/.gvfs/Documents on “HuangWei”的 iPhone/com.tencent.xin/MicroMessenger.app$ ll in.caf
-rwx------ 1 hweicdl hweicdl 38528 Aug 28  2013 in.caf*

虽然ls显示是有写权限的,但事实并非如此,so这些应用下的所有文件都是可读的。不过也还算不错了,不像在windows上,只在iTunes里显示某些可以上传文档的应用。所以这里能发挥的也就不多了,不过也算是非越狱环境下能做的一些有意思的事情了。

如果有对gvfs-mount方式感兴趣的,下面是相关的命令:

 idVendor=$(lsusb -v 2>/dev/null | awk '/idVendor.*Apple/{print $2; exit}')
 iSerial=$(lsusb -v -d $idVendor: 2>/dev/null | awk '/iSerial/{print $3; exit}')
 gvfs-mount afc://$iSerial/

后记

这里有一个小插曲,这篇blog我断断续续写了有一会儿了,中间我把iPhone升到了7.1,然后一直遇上“是否信任”的死循环问题,充电倒是能继续充,但所有的文件都看不见了。之到我按照这篇文章把这个fix了之后,一切又重见天日了。