Automount a specific USB drive


Actually this is a straight forward thing, however since it has been a while I had to google it myself, and was astonished about how many non-working solutions I found, besides solutions that simply mount every USB according to their label. So here is the straight forward solution to mount a specific USB device to a specific location on your Unix hierarchical file system, using udev. It assumes that you have a running version of udev, and the udev tools. If not, please consult the distribution specific documentation on the Linux distribution of your choice. This might include recompiling your Kernel, as udev will need the following settings:

General setup --->
[*] Configure standard kernel features (expert users) --->
[ ] Enable deprecated sysfs features to support old userspace tools
[*] Enable signalfd() system call
Enable the block layer --->
[*] Block layer SG support v4
Networking support --->
Networking options --->
<*> Unix domain sockets
Device Drivers --->
Generic Driver Options --->
() path to uevent helper
[*] Maintain a devtmpfs filesystem to mount at /dev
< > ATA/ATAPI/MFM/RLL support (DEPRECATED) --->
File systems --->
[*] Inotify support for userspace
Pseudo filesystems --->
[*] /proc file system support
[*] sysfs file system support

As for Gentoo Linux, the other things you will want to do, is to add “udev” to your USE-flags (by adding it into your /etc/portage/make.conf), get udev installed (calling emerge -avuD sys-fs/udev), and add udev to your sysinit runlevel (rc-update add udev sysinit).

Now to the fun part. First of all you need to get some information about the device you are interested in. There are a number of ways, like using udev monitor, etc. Most of them, to me however, are too messy. If you have no idea about your device and still need to figure things out, blkid -o list will show you a nice table of all devices, their device file, file system type, label, mount point and UUID – everything you need. For me, I know I have a stick with the label “Public” on an OS X with file system type exFat, and now I inserted it into a dual boot Linux with a number of partitions:

ancalagon ~ # blkid -o list
device                            fs_type      label         mount point                           UUID
---------------------------------------------------------------------------------------------------------------------------------------
/dev/sdb1                         vfat                       /boot                                 58FB-332D
/dev/sdb2                         swap                       [SWAP]                                73db158f-0e19-4d17-8c88-a8b0c1dff1f3
/dev/sdb3                         ext4                       /home                                 355af6d8-6f03-4a98-9a45-edafc3ccedde
/dev/sdb4                         ext4                       /                                     63be67f3-5c7c-48ea-a8b3-58dff9da1737
/dev/sda1                         ntfs         Wiederherstellung (not mounted)                     562065062064EF05
/dev/sda2                         vfat                       (not mounted)                         6265-B138
/dev/sda4                         ntfs                       (not mounted)                         6C58731C5872E46C
/dev/sdc1                         exfat        Private       /media/private                        56B6-CE90
/dev/sdd1                         exfat        Public        (not mounted)                         56BE-6477
/dev/sda3                                                    (not mounted)

If you want more information, with the device file you can get it with:

ancalagon ~ # udevadm info /dev/sdd1

I want the stick to be mounted at /media/public, so I need to create a rule file; on Gentoo it lies under /etc/udev/rules.d/90-local-usb.rules. Actually the name is totally arbitrary, except for the number at the beginning, and the extension that always has to be .rules. The number should be something high, because we want udev to first run all other rules (e.g. the ones that assign the device to a device file) before running ours. 90 is a good value for that.

So in my case, this is what I added:

SUBSYSTEMS=="usb", ENV{ID_FS_UUID}=="56BE-6477", ACTION=="add", RUN+="/usr/bin/logger --tag udev Mounting public", RUN+="/bin/mount -o umask=0077,nosuid,uid=1000,gid=1001 '%E{DEVNAME}' /media/public"

We need to provide the system or subsystem, which for an USB device is usb. The UUID comes from blkid and identifies the device. The action triggers when to run the command. In our case, when a new USB device is added and it has the UUID we want. And finally the mount command. I’ve added another command such that there is a log entry but thta is no need. And as I want it to be accessible as user, I added uid and gid accordingly. If you need to find out your user and group id, just run:

ancalagon ~ # id -u 
ancalagon ~ # id -g 

And that’s it. If you want to see if the rule triggers, just run

ancalagon ~ # tail -f /var/log/everything/current

It should output:

[udev] Mounting public

somewhere. And you can <em>simulate</em> the USB event with udevadm, by triggering the rule you just wrote (although this is rather interesting for more general rules that should fit more than just one device). This is how it’s done:

ancalagon ~ # udevadm trigger --action="add" --property-match=ID_FS_UUID="56BE-6477"

Non-breakable Space Problems


On OS X and apparently also some Unix-based machines you may have encountered a strange behaviour (in my experience especially on Laptop keyboards). On the shell it sometimes might just happen that you pipe something and get an error message. E.g.

pygospa@lalaith ~ % ls -ahl | grep .log
zsh: command not found:  grep

Retyping it may then bring you:

pygospa@lalaith ~ % ls -ahl | grep .log
-rw-r--r--    1 pygospa  staff    54B 15 Nov 11:55 tmux-client-8140.log
-rw-r--r--    1 pygospa  staff    24K 15 Nov 11:55 tmux-server-8142.log

So, what just happened? To me this actually happens so seldom that I never even bothered to try understanding. Therefore I often encountered another problem wich started annoying me. When editing a TeX-File, every now and then I got this error message:

! Package inputenc Error: Unicode char \u8:  not set up for use with LaTeX.
l.193 \end{align*}

I discovered that rewriting (not copying!) the line does some good. So it had to be some non-printing control character, and after searching for “OS X, Latex \u8 error” (I initially assumed that it must be an OS X thing, as I never encountered it in LaTeX on my Linux days – I now assume that it’s rather a Keyboard thing) I found a quick and dirty solution to it, adding this line:

\DeclareUnicodeCharacter{00A0}{ }

So the non-visible Unicode sequence was overwritten with a space. And thus I was never bothered again when editing LaTeX.

But now, while writing some RSpecs for a Ruby on Rails project I am working on it occurred again, and in RSpec there’s no quick and dirty solution that can be written into some preamble to fix an input error.

Continue reading

Put some colour in your life!


This one-liner is a pretty harmless and easy one, yet very very useful (as you might be seeing in one of my next entries).

for i ({000..255}){[ $((i%20)) = 0 ] && printf "\n";printf "\x1b[38;5;${i}m${i} "}

This will actually just work in the Z-Shell, there’s a slightly longer version you’d have to use if you don’t use the Z-Shel (you masochist! 😉 ).

i=0;while [ $i -le 255 ];do [ $((i%20)) = 0 ] && printf "\n";printf "\x1b[38;5;${i}m${i} ";i=$(($i+1));done

What does it do? Well I’ll show you a more comfortable version of it:

i=0;
while [ $i -le 255 ]
do
    if [ $((i%20)) = 0 ]
    then
        printf "\n"
    fi
    printf "\x1b[38;5;${i}m${i} "
    i=$(($i+1));
done

If you ever worked with colors in the shell, you might right away see it: It’s the CSI codes for colors defined by the ANSI escape sequences. So the script goes through all possible 255 color codes that are available on your systems shell and prints the corresponding number in its color. By making use of every shells lazy evaluation the if <cond>; then; <expr>; fi becomes the neat and compact <cond> && <expr>. Making use of Z-Shells highly sophisticated brace expansion our i=0; while <$i-cond>; do; <expr>; <$i-expr>; done becomes for i in <brace>; do <expr>; done. The brace expression is then evaluated to a list from 000, 001,… to 099 and then further on to 255, so it is as if all those numbers were actually written out as list (which is why we can use for in this case). Using the short form of for-loops in zsh it then becomes for i (<brace>){<expr>}. Neat and sweet, wouldn’t you say?

Now you could even make it more compact, if you don’t care about how it is broken into lines (that’s why there’s the modulo part printing an printf “\n” after each 20 numbers (thus with space 4 chars * 20 = 80 chars per line), you could remove it and end up with printing one huge line, or even one huge column:

for i ({000..255}){ printf "\x1b[38;5;${i}m${i}\n"}

Why bother? Well let me lose some short thoughts on that:

Continue reading