Friday, December 26, 2008

Listing Storage Devices That Contain A File System

Here's a script that finds (using HAL) all the storage devices containing a file-system (except for optical discs) that are attached to a given machine, whether or not they are mounted:

#! /bin/bash
hal-find-by-property --key volume.fsusage --string filesystem |
while read udi ; do
# ignore optical discs
if [[ "$(hal-get-property --udi $udi --key volume.is_disc)" == "false" ]]; then
dev=$(hal-get-property --udi $udi --key block.device)
fs=$(hal-get-property --udi $udi --key volume.fstype)
echo $dev": "$fs
fi
done

This was my answer to a question on stackoverflow.com, during the few days that I thought that website was worth the time. I got over it.

(see a previous post of mine, for another example of stuff that can be done with HAL)

Friday, December 19, 2008

Override (Supersede) DHCP Network Interface Configuration

Suppose you find out that the MTU reported by the DHCP server, to the DHCP client on your box, is, for some reason, incorrect, and you end up with a mis-configured network interface.

There's a workaround until the problem is fixed on the server side - you can override that (and any other) value with a supersede statement in /etc/dhcp3/dhclient.conf, like this:

interface "eth1" {
supersede interface-mtu 1500;
}

(reference: the dhclient.conf man page)

Friday, December 12, 2008

Cropping Pages in Scanned PDF Files

Here's a script that takes a PDF file containing a scanned document whose pages are surrounded by an annoying black margin, extracts all pages from it, crops every page to a (common) desired geometry and then joins them back:

#! /bin/bash
# usage:
# pdf-crop.sh path/to/file.pdf geometry
# see 'man convert' for geometry syntax (example: 100%x90%+750)
mkdir -p "/tmp/$1"
echo "Extracting images..."
pdfimages -j "$1" "/tmp/$1/image"
echo "Cropping images..."
list=$( \
find "/tmp/$1/" -name "image-*.pbm" -o -name "image-*.ppm" -o -name "image-*.jpg" | sort | \
while read file ; do \
pdffile="${file}.pdf" ;\
printf "\"%s\" " "${pdffile}" ;\
convert -crop "$2" "$file" "$pdffile" ;\
done \
)
echo "Joining images..."
eval "pdfjoin --outfile \"""${1/%.pdf/.cropped.pdf}""\" "${list}

The script depends on pdfimages, convert and pdfjoin:
aptitude install xpdf-utils imagemagick pdfjam

And just in case you're wondering - the script started out simple, but there are spaces in the name of the PDF file that I used for testing, which turned out to be rather tricky to handle.

Friday, December 5, 2008

Running A Script Upon External Disk Removal

A while ago I posted here about how I use a udev rule for triggering the backup of an external USB disk upon being connected to my box.

The udev rule matches both the kernel device name with a wildcard (because it's assigned dynamically) and the device's serial number (which is supposed to be a unique device attribute), and then installs an easy to remember symbolic link to the device and runs the backup script:

KERNEL=="sd?1", ATTRS{serial}=="300000064029", ACTION=="add", SYMLINK+="aluminum", RUN+="/path/to/script"

I now need to run another script when this external USB disk is disconnected.

At first it looked easy enough to accomplish: copy and paste the rule above, replace ACTION=="add" with ACTION=="remove", remove the SYMLINK bit and modify the path to the script.

I was surprised to find out that the script was never called - the remove event did not seem to fire. It took a few anxious minutes, with several physical connects and disconnects of the external disk, before I figured it out.

It seems that when the disk is removed, the conditional ATTRS{serial}==... is always false - presumably because the device attribute called serial is gone and can't be matched against. The correct (read: working) approach is to match against the symbolic link, like this:

SYMLINK=="aluminum", ACTION=="remove", RUN+="/path/to/post/removal/script"

I bet Linus Torvalds drives a car with a manual gearbox.
I guess Bill Gates has a chauffeur.
And Steve Jobs... well, he simply teleports.