Friday 5 October 2012

Auto-rip CDs on headless server using udev and abcde

I have a lot of CDs, at least 500. Some of them have over the last few years made their way in FLAC form to the hard disk of my main PC, but now this collection is on the server, I'd like to add the rest of the CDs to the digital library and finally store them out of the way. I wanted a way for the server to do the work of ripping the CDs without any user intervention apart from putting a CD in the drive and taking it out again.

Linux's udev system provides a way for programs to be triggered on hardware events, such as a CD being inserted. In Fedora, udev rules files can be added to /etc/udev/rules.d/ and they will be magically picked up and used.

I wrote a rules file that looked like this:
/etc/udev/rules.d/99-autoripcd.rules

SUBSYSTEM=="block", KERNEL=="sr0", ENV{ID_CDROM_MEDIA_CD}=="1", RUN+="/usr/bin/cdautoinsert" 

Simply, this looks in sysfs's /sys/block/sr0/ for a CD (instead of a DVD) to be inserted, and runs the commmand given by RUN+. This is a shell script which runs the useful cd ripper, abcde. Here is the script:
/usr/bin/cdautoinsert

#/bin/bash

PATH=/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin /bin/abcde -NVP | tee /var/log/abcde-auto.log &

exit

The key to getting this working (and which took some googling to work out) is to pass a PATH to whatever commands you run in the script. This is because udev runs commands (as root) without much of an environment, and abcde was failing to find cdparanoia and the other tools it relies on. The other useful thing to know is to make sure commands are run with & to make the shell detach those processes, otherwise udev will hang until the job is complete, which is about 5 minutes for a typical cd.

I edited /etc/abcde.conf to give abcde defaults that work for me, including:
INTERACTIVE=n     (the -N switch on abcde's command line also does this)
ACTIONS=cddb,read,encode,tag,move,clean
OUTPUTTYPE=flac
OUTPUTFORMAT='${ARTISTFILE}/${ALBUMFILE}/${ARTISTFILE}-${ALBUMFILE}-${TRACKNUM}.${TRACKFILE}' (this fits with the directory structure of my music collection)
EJECTCD=y


When writing your own udev rules, the udevadm tool is handy.
udevadm monitor will show udev events as they happen (so you can see which subsystem to look at)
udevadm info --name=/dev/sr0 --query=all will list everything udev knows about the CD drive