A small email to sumarize some thoughts about udev, removable storage and incron to make the job of hal and re-invent the wheel.
---- context (skipable) -----
there is ONE common thing where gnome is quicker than bash : mounting
an unknown usb stick.
For my own stuff, I already used labels and uuids for ages but for
stranger devices it's not possible.
So those are the steps I did thousands of times :
- grab root (the device can be sdc3 as sde1 so there is no specific fstab entry)
- [dmesg|tail to check the device name or bash completion]
- mount -o users,rw /dev/new_device_X /mnt/remusb
- ^D
- cd /mnt/remusb
So what I needed was to get my plugged devices automounted to have
quickly a terminal in the directory. (I use fluxbox without idesk or
whatever)
Here comes the solution I found :
---- configuration -----------
FSTAB : some lines of /etc/fstab
LABEL=docus /home/ftp/pub/Docus ext3 users,auto
0 0
UUID=0467-FFC1 /mnt/mp3 vfat users,rw,noatime
0 0
UDEV : some lines of /etc/udev/rules.d/80-custom.rules
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="docus", "RUN+="/bin/mount
-L docus"
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_UUID}=="0467-FFC1",
RUN+="/bin/mkdir -p /mnt/mp3", RUN+="/bin/mount -U 0467-FFC1"
Ok, so this UDEV rules only make KNOWN devices automounted (but
nothing for unknown devices)
I then needed to have unknown devices mounted into /mnt/remusb, so the
other devices are given a $ENV{} variable.
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="docus", RUN+="/bin/mount
-L docus", ENV{custom_rules}="add"
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_UUID}=="0467-FFC1",
RUN+="/bin/mkdir -p /mnt/mp3", RUN+="/bin/mount -U 0467-FFC1",
ENV{custom_rules}="add"
# so I can add :
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[b-z][1-9]",
ENV{custom_rules}=="", RUN="mkdir -p /mnt/remusb", RUN+="mount /dev/%k
/mnt/remusb"
But as I have many more removable medias, I factorised the code and used
exclusively ENV{} like the following :
## definitions examples :
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="integral",
ENV{mount_point}="integral", ENV{mount_cmd}="-L integral",
ENV{custom_rules}="add"ACTION=="add", SUBSYSTEM=="block",
ENV{ID_FS_LABEL}=="docus", ENV{mount_cmd}="-L docus", ENV{custom_rules}="add"
## actions :
ENV{custom_rules}=="add", ENV{mount_point}!="", RUN+="/bin/mkdir -p
/mnt/$env{mount_point}"
ENV{custom_rules}=="add", ENV{mount_cmd}!="", RUN+="/bin/mount $env{mount_cmd}"
--------------------
Now I want to be notified !
2 solutions :
- the bad one, udev runs as root : who && su -l my_user && DISPLAY=:0 osd_cat
"new
device"
- another one, use a per-session user daemon (as I ignored the hal
documentation I didn't even looked at dbus-launch or others hal
"plugins").
I decided to be notified by a file creation : INCRON
UDEV has to create a file in a directory monitored by incron.
[The creation a file whose name gives some useful information monitored by a
daemon
is a kind a replacement of a real bus messaging system]
So, in the udev rule for my mp3 player I add the following :
RUN+="/bin/mkdir /tmp/.incron.device/%k"
(in fact I added it as the last one of the "actions" part of the udev rules
file)
For my user I create a incrontab like :
/tmp/.incron.device IN_CREATE,IN_DELETE /home/myuser/.automount-script.sh $@ $#
$%
So it's now possible to control what to do as udev notify us by incron,
better, monitoring /proc/partitions or whatever is useless as udev passes the
device name to incron which forward it to the script.
Example of automount-script.sh :
if [[ $theevent =~ IN_CREATE ]]; then
destdir=$(mount|sed -n "s;^/dev/$thedevice on \(.*\) type.*$;\1;p")
urxvtc -cd $destdir
fi
In that way I have a terminal spawned in the mount point each time
a removable device is plugged.
I attached my fstab, udev rule, incrontab -l and custom script.
I would be curious to read some advices about this architecture.
I also have 2 questions :
- what's the way to have a incremental number for unknown devices like
/mnt/remusb1 then /mnt/remusb2 instead of /mnt/remusb (within udev) ?
- where to put the creation of /tmp/.incron.device in the init scripts
to be sure it will be created BEFORE incron starts (without having to
create a new startup script) ?
Raph
/tmp/.incron-device IN_CREATE,IN_DELETE /home/yug/.incron-script.sh $@ $# $%
LABEL=swap none swap sw
0 0
LABEL=boot /boot ext2 noauto,noatime
1 2
LABEL=slash / reiserfs noatime
0 1
LABEL=usr /usr reiserfs noatime
0 0
LABEL=var /var reiserfs noatime
0 0
LABEL=log /var/log reiserfs noatime
0 0
LABEL=home /home reiserfs noatime
0 1
LABEL=compilationdir /var/tmp reiserfs noatime
0 0
/dev/scd0 /mnt/cdrom iso9660 noauto,ro,user
0 0
LABEL=integral /mnt/integral ext3 users,noauto
0 0
LABEL=docus /home/ftp/pub/Docus ext3 users,auto
0 0
LABEL=films /home/ftp/pub/Films2 ext3 users,auto
0 0
LABEL=gris2 /mnt/gris2 ext2 users,rw,noauto,noatime
0 0
UUID=0467-FFC1 /mnt/mp3 vfat users,rw,noatime
0 0
none /proc proc defaults
0 0
none /dev/shm tmpfs nodev,nosuid,noexec
0 0
none /tmp tmpfs
defaults,mode=1777,size=100m 0 0
none /var/run tmpfs
defaults,noexec,size=150k 0 0
/dev/fd0 /media/floppy auto rw,user,noauto
0 0
none /mnt/debugfs debugfs auto
0 0
## WE DOESN'T CREATE A SPECIFIC SYMLINKS IF OUR FSTAB CONFIGURED THE LABELS
## USB STICK GRIS
ACTION=="add", SUBSYSTEM=="block",
ENV{ID_FS_UUID}=="0e2bd8c1-d14d-4bf9-bed9-a5e5acfd7b08", SYMLINK+="gris1",
ENV{custom_rules}="notyet"
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="gris2",
ENV{mount_point}="gris2", ENV{mount_cmd}="-L gris2", ENV{custom_rules}="add"
ACTION=="remove", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="gris2",
ENV{mount_point}="gris2", ENV{custom_rules}="remove"
#ACTION=="add", SUBSYSTEM=="block",
ENV{ID_FS_UUID}=="425a5f7d-d75c-4470-bd19-fc56b2724210", SYMLINK+="gris2"
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_UUID}=="B109-EE46",
SYMLINK+="gris3", ENV{custom_rules}="notyet"
## TESTS
#KERNEL=="sdb[123]", ENV{ID_SERIAL}=="USB_2.0_Flash_Disk_A000000000000233",
SYMLINK+="gris_ker_env_ser"
#KERNEL=="sdb[123]", ATTRS{serial}=="USB_2.0_Flash_Disk_A000000000000233",
SYMLINK+="gris_ker_attrs_ser"
#KERNEL=="sdb[123]", ENV{ID_SHORT_SERIAL}=="A000000000000233",
SYMLINK+="gris_ker_env_shser"
#KERNEL=="sdb[123]", ATTRS{short_serial}=="A000000000000233",
SYMLINK+="gris_ker_attrs_shser"
## WESTERN DIGITAL
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="docus",
ENV{mount_cmd}="-L docus", ENV{custom_rules}="add"
#ACTION=="add", SUBSYSTEM=="block",
ENV{ID_FS_UUID}=="f2574b18-3fa6-4649-9908-eaa8503cab33", SYMLINK+="wd1"
ACTION=="remove", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="docus",
ENV{custom_rules}="remove"
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="films",
ENV{mount_cmd}="-L films", ENV{custom_rules}="add"
#ACTION=="add", SUBSYSTEM=="block",
ENV{ID_FS_UUID}=="08fea226-c5a5-49de-a8e7-bfc2a9975232", SYMLINK+="wd2"
ACTION=="remove", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="films",
ENV{custom_rules}="remove"
## MP3 PLAYER
#ATTRS|ENV : "Samsung_YP-U1_0002F6916425CF08-0:0", SYMLINK+="mp3"
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_UUID}=="0467-FFC1",
ENV{mount_point}="mp3", ENV{mount_cmd}="-U 0467-FFC1", ENV{custom_rules}="add"
ACTION=="remove", SUBSYSTEM=="block", ENV{ID_FS_UUID}=="0467-FFC1",
ENV{mount_point}="mp3", ENV{custom_rules}="remove"
## INTEGRAL USB HD
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="integral",
ENV{mount_point}="integral", ENV{mount_cmd}="-L integral",
ENV{custom_rules}="add"
ACTION=="remove", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="integral",
ENV{mount_point}="integral", ENV{custom_rules}="remove"
#ACTION=="add", SUBSYSTEM=="block",
ENV{ID_FS_UUID}=="d588d4d2-6904-4623-960c-707409bcb9c3", SYMLINK+="integral"
## UNKNOWN DEVICES
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[b-z][1-9]",
ENV{custom_rules}=="", RUN="mount /dev/%k /mnt/remusb", RUN+="/bin/mkdir
/tmp/.incron.yug/%k"
## RUN THE FACTORIZED BABE
ENV{custom_rules}=="add", ENV{mount_point}!="", RUN+="/bin/mkdir -p
/mnt/$env{mount_point}"
ENV{custom_rules}=="add", ENV{mount_cmd}!="", RUN+="/bin/mount $env{mount_cmd}"
ENV{custom_rules}=="add", RUN+="/bin/mkdir /tmp/.incron.yug/%k"
ENV{custom_rules}=="remove", ENV{mount_point}!="", RUN+="/bin/rmdir
/mnt/$env{mount_point}"
ENV{custom_rules}=="remove", RUN+="/bin/rmdir /tmp/.incron-device/%k"
automount-script.sh
Description: Bourne shell script

