Mounting a USB drive, always in the same location

Tags:

[Applies specifically to Ubuntu 10.10 and generally to current Linux distros.]

So you have one of those nifty new terabyte USB attached hard drives. (We used to call them Winchester drives, and they used to be 5, 10, or maybe a whopping 20 megabyes... whippersnappers!)

And instead of having it mount at something like /media/7d1fdc53-00e0-4057-8e34-80feedbe495d you would prefer something more like /media/lunchbox that you can remember, and that fits on your screen.

Ready? OK, make sure your drive is powered on and plugged in. You could read the output of dmesg but let's assume the drive has been mounted awhile, and ask mount where it is (typed text underlined):

<small>$ <span style="text-decoration: underline;">mount</span>
/dev/sda5 on / type ext4 (rw,relatime,errors=remount-ro,commit=0)
proc on /proc type proc (rw)
none on /sys type sysfs (rw,noexec,nosuid,nodev)
fusectl on /sys/fs/fuse/connections type fusectl (rw)
none on /sys/kernel/debug type debugfs (rw)
none on /sys/kernel/security type securityfs (rw)
none on /dev type devtmpfs (rw,mode=0755)
none on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
none on /dev/shm type tmpfs (rw,nosuid,nodev)
none on /var/run type tmpfs (rw,nosuid,mode=0755)
none on /var/lock type tmpfs (rw,noexec,nosuid,nodev)
/dev/sda1 on /boot type ext2 (rw,relatime)
/dev/sda6 on /home type ext4 (rw,relatime,commit=0)
cgroup on /dev/cgroup/cpu type cgroup (rw,cpu)
gvfs-fuse-daemon on /home/bill/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=bill)
<strong>/dev/sdb1</strong> on <strong>/media/7d1fdc53-00e0-4057-8e34-80feedbe495d type ext3</strong> (rw,nosuid,nodev,<strong>uhelper=udisks</strong>)
$</small>

Ah, see that uhelper=udisks ? That tell us the udev manager has control of /dev/sdb1 ... which must be our drive, and it is attached to the /dev/sdb1 device node. If your list is longer or has multiple entries, you will have to look around to see which mounted drive you want.

udev is the user-mode device manager [wikipedia] which was introduced for Linux Kernel 2.6. We could write a udev rule, but apparently there have been several versions of rule syntax, all of which are now broken and all the web pages I could find were obsolete. Way to go, software authors, keep changing your rules and breaking our config files. Feh. Brain-dead stuff like that keeps the "Linux is hard" going! Grrr. (See footnote.)

With that in mind we find the "UUID" of the filesystem (if you reformat the partition, the new filesystem in it will have a different UUID).

<small>$ <span style="text-decoration: underline;">ls /dev/disk/by-uuid -lah</span>
total 0
drwxr-xr-x 2 root root 140 2010-12-31 05:32 .
drwxr-xr-x 5 root root 100 2010-12-30 19:24 ..
lrwxrwxrwx 1 root root  10 2010-12-30 19:25 2909c529-b30f-45ae-bde7-a3342a922a55 -> ../../sda6
lrwxrwxrwx 1 root root  10 2010-12-31 05:32 <strong>7d1fdc53-00e0-4057-8e34-80feedbe495d</strong> -> ../../sdb1
lrwxrwxrwx 1 root root  10 2010-12-30 19:25 ca40739e-ad5d-4961-a469-0b9dc86e7973 -> ../../sda1
lrwxrwxrwx 1 root root  10 2010-12-30 19:25 d93f0664-ea69-4199-8c77-ffd5960bfcd1 -> ../../sda2
lrwxrwxrwx 1 root root  10 2010-12-30 19:25 ea2707dc-418b-4000-8ee4-172abc1e5274 -> ../../sda5
</small>

Ah there it is on sdb1. In most cases that big UUID number will be the in udev mountpoint, but who knows how udev might change. So... Let's create the mountpoint we will use:

$ sudo mkdir /media/lunchbox

Note that mount points under /mnt do not show up in "Places" or on your desktop, since they are considered fixed; mounts under media are better used for things like USB drives which are considered removable.

Now we add a line to /etc/fstab ... perhaps $ emacs /etc/fstab if you prefer emacs, or you could always use vi if you insist... anyway add this line:

UUID=7d1fdc53-2a5b-4d23-8e34-80ffb1be495d /media/lunchbox auto user,rw,nosuid  0 0

That specifies the filesystem by its UUID, the mount point we want, auto filesystem detection, user so users can mount, rw for read/write access, and nosuid so folks can't create scripts with root ownership on another system and run them here.

Now unmount and replug your device and you should have /media/lunchbox online!

#

What didn't work.

I tried to write a "udev rule" -- there are plenty of instructions but every page I could find in google gave me directions that are broke under Ubuntu 10.10. Numerous older blogs will point you to instructions for udevinfo but that was removed from many distros circa 2009, along with several other commands that all got merged into udevadm. Unfortunately the new command is a little more complex to use.

I was able to invoke udevadm to find out my drive's serial number. This all goes on one line (the characters let us type it on several lines, so copy and paste it just this way). The bold text is our device node from above.

udevadm info -a -p `udevadm info -q path -n <strong>/dev/sdb1</strong>` | 
grep ATTRS{serial} | head -1  | sed s/"ATTRS{serial}==""//g | 
sed s/"// | tr -d " "

On my system, this printed:

57442D574341505732373938353536

Next we create the file

$ sudo umount /dev/sdb1

If things go wrong, examine the system log file:

$ sudo less /var/log/syslog

for clues.

For example I followed an older how-to and created the file /lib/udev/rules.d/91-usbmount.rules (which the howto admonished me had been moved "from rules.d to rules in recent versions of Ubuntu" -- which was wrong, it's still in rules.d in 10.10). OK so here is what I put, on one line:

BUS=="usb", ATTRS{serial}=="57442D574341505732373938353536" ,
KERNEL=="sd?1", NAME="%k", SYMLINK+="lunchbox",  GROUP="storage"

Which just gave me these messages in syslog:

Dec 31 05:00:33 charcoal udevd[326]:
  BUS= will be removed in a future udev version, please use SUBSYSTEM=
  to match the event device, or SUBSYSTEMS= to match a parent device,
  in /lib/udev/rules.d/91-usbmount.rules:1
Dec 31 05:00:33 charcoal udevd[326]: NAME="%k" is ignored, because it
  breaks kernel supplied names, please remove it from
  /lib/udev/rules.d/91-usbmount.rules:1
Dec 31 05:00:33 charcoal udevd[326]: specified group 'storage' unknown

Rah.