/ root / pages / automounting.html

You're using an old link! - Thankfully, you no longer need to specify a nonstandard port (8080) to access my site. You could've used the more standard: http://pbrisbin.com/pages/automounting.html.

Automounting


It seems as users (myself inclusive) progress through the stages of using a distribution like Arch linux, they reach certain stages. Like when you realize how amazing find -exec is. Or crossing over from god, vim is a pain in the ass! to jesus, why doesn't everyone use this?

I find one well-known stage is how can I automount my USB drives? This usually comes early on as a new Arch user ditches GNOME or KDE in favor of something lighter, something more minimalistic, something he can actually be proud to show off in the screenshot thread. Well, ditch the DE and you lose all those nifty little automagical tools, like gnome-volume-manager and the like.

So what do you do? hal should take care of it. Some ck-launch-session black magic might do the trick. Edit some *.fdi file to get it going?

No. Udev does just fine.

Udev

Udev has a little folder called /etc/udev/rules.d. In this folder, are 'rules files' each named 10-some-crap.rules. They are processed one by one each time some udev 'event' occurs, like, say, plugging in a flashdrive. [ sidenote: go google udev rules, there's alot out there for all sorts of nifty things. ]

Someone smarter than I added a handful of useful rules to the Arch udev wiki page. The one I use is as follows:

  # adjust this line to skip any persistent drives
  # i.e. KERNEL!="sd[d-z][0-9]", ...
  KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"

  # Global mount options
  ACTION=="add", ENV{mount_options}="relatime,users"
  # Filesystem specific options
  ACTION=="add", PROGRAM=="/lib/initcpio/udev/vol_id -t %N", RESULT=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002"

  ACTION=="add", PROGRAM=="/lib/initcpio/udev/vol_id --label %N", ENV{dir_name}="%c"
  ACTION=="add", PROGRAM!="/lib/initcpio/udev/vol_id --label %N", ENV{dir_name}="usbhd-%k"
  ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}"
  ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"
  LABEL="media_by_label_auto_mount_end"

This file defines how udev reacts to usb drives (/dev/sda1, etc) being added and removed. You plug in a flashdrive, if it has a label, it's mounted at /media/<label>; if not, it's mounted at /media/usbhd_sda1 (for example). umount and remove the drive, and that directory under /media is removed. It's a beautiful thing.

Automount

One problem I found with this is that it works really well. When a device is added it is mounted, period. So whenever I tried to partition a drive, as soon as the partition was initialized it would get mounted, and the partitioning tool would fail with drive is mounted.

For this reason, I had to write a script. I always have to write a script.

What this does is simply write the above rules file or remove it. This effectively turns automounting 'on' or 'off'.

Update - I've updated my script a bit from what was originally here. First, it now uses start, stop, and restart as args like the default arch init scripts. It also sources rc.d/functions so that you get those colorful BUSY, DONE messages like default daemons. Lastly, I added a helper function to dynamically choose the starting letter for the udev rule. I.e. if you have 3 physical drives connected when you call automount start, the udev rule will be written to apply to /dev/sd[d-z] only.

Here's the live script:

#!/bin/bash
#
# pbrisbin 2009, 2010
#
# http://pbrisbin.com/bin/automount
#
# just moves a rules file about to change udev behavior regarding the
# automounting of usb devices. 
#
# see http://wiki.archlinux.org/index.php/Udev for details.
#
###

USECOLOR='YES'

# get those fun BUSY/DONE messages
. /etc/rc.d/functions

# if this file's present, automounting is 'on'
file='/etc/udev/rules.d/11-media-by-label-auto-mount.rules'

message() { echo 'usage: automount [ start | stop | restart ]'; exit 1; }

# find the number of in-use drives and get the next available letter
get_next_letter() {
  local alph n
  
  alph=( $(echo {a..z}) )
  n=$(ls /dev/sd? 2>/dev/null | wc -l)

  echo "${alph[n]}"
}

# mount as /media/<label> or fall back on usbhd-sdxy
write_file() {
  local a="$(get_next_letter)"

  [[ -z "$a" ]] && return 1

  # 7/10/2010 + rule updated
  cat > "$file" << EOF
KERNEL!="sd[$a-z][0-9]", GOTO="media_by_label_auto_mount_end"

# Import FS infos
IMPORT{program}="/sbin/blkid -o udev -p %N"

# Get a label if present, otherwise specify one
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="usbhd-%k"

# Global mount options
ACTION=="add", ENV{mount_options}="relatime,users"
# Filesystem-specific mount options
ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="\$env{mount_options},utf8,gid=100,umask=002"

# Mount the device
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o \$env{mount_options} /dev/%k /media/%E{dir_name}"

# Clean up after removal
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"

# Exit
LABEL="media_by_label_auto_mount_end"
EOF

}

# write out the file to enable automounting
turn_on() { 
  stat_busy 'Turning on automount'
  [[ -f "$file" ]] || write_file && stat_done || stat_fail
}

# remove the file to disable automounting
turn_off() { 
  stat_busy 'Turning off automount'
  [[ -f "$file" ]] && rm "$file" && stat_done || stat_fail
}

check_state() { [[ -f "$file" ]] && echo 'on' || echo 'off'; exit 0; }

# no args will just print current state
[[ -z "$1" ]] && check_state

# must be root to change things
[[ $(id -u) -ne 0 ]] && exit 1

case "$1" in
  start)   turn_on           ;;
  stop)    turn_off          ;;
  restart) turn_off; turn_on ;;
  *)       message           ;;
esac

So there you go, simple handling of usb flash drive with nothing but udev required.

DVDs and CDs

Just a bit about optical media. The above won't solve any issues related to that. I'll just say this though, if I need to do anything related to CDs or DVDs, I can just reference /dev/sr0 directly. Burning images, playing DVDs, it all works just fine using /dev directly. And when I need to mount it, I'll do it manually. I think a line in fstab will get /dev/sr0 to mount to /media/dvd if that's what your after.

Comments

on Sun, 11 Jul 2010 17:03:07 -0400, GUsunaito wrote:

Hello i like much this.
Works charms.
But how do i auto change persmisions to no root can modify files?

on Mon, 12 Jul 2010 09:59:45 -0400, me wrote:

You should change ENV{mount_options} to whatever you need. The first applies to all drives, the second only to vfat/ntfs drives.

I mount mostly vfat drives with this method and I can read/write files as user no problem.

on Sat, 31 Jul 2010 05:39:57 -0400, lucapost wrote:

My personal solution for mount usb device is uam : http://qwpx.net/~mgorny/uam/

on Sun, 08 Aug 2010 18:38:21 -0400, me wrote:

lucapost, FYI: I get a 403: forbidden on that link.





pbrisbin dot com 2010