Monday, December 16, 2013

Initialize (partition, format, copy) multiple USB sticks using linux and udev

Here's a set of scripts that allows you to fill hundreds of USB sticks with the same data. We used that for distributing proceedings of a conference, but I guess it might be helpful for others, too.

It should work on pretty much any recent linux distribution, as it only requires UDEV to work.

First, create or edit /etc/udev/rules.d/10-local.rules and add
ATTRS{idVendor}=="VENDOR_ID_OF_USB_STICK", ATTRS{idProduct}=="PRODUCT_ID_OF_USB_STICK", ATTR{size}=="15810560", RUN+="/usr/bin/fill_usb_stick.sh %k"
Then create /usr/bin/fill_usb_stick.sh, which reads:
#!/bin/bash { # Convert /dev/sdb into sdb UNIQUENAME=$1 DEVICEFILE="/dev/$1" PARTITION="/dev/$11" if [[ "$ACTION" = "remove" ]] then echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME was removed." >> /tmp/log.txt exit 0 fi if [[ "$ACTION" != "add" ]] then exit 0 fi LOCKFILE="/tmp/lock_usb_$UNIQUENAME" test -e $LOCKFILE && echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: already running, exiting" >> /tmp/log.txt && exit 1 touch $LOCKFILE if [[ "$UNIQUENAME" == "sda" ]] then echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: Will not write to SDA, exiting" >> /tmp/log.txt exit 1 fi /usr/bin/logger "setting up usb stick $UNIQUENAME due to action $ACTION" echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: creating new partition table, filesystem and proceedings on usb stick" >> /tmp/log.txt cat <> /tmp/log.txt # Create a FS on the first partition /sbin/mkfs.vfat -n MFI_2012 $PARTITION if [[ -d /mnt/$UNIQUENAME ]] ; then /bin/rmdir /mnt/$UNIQUENAME if [[ $? != 0 ]] ; then echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: EEEEE could not delete /mnt/$UNIQUENAME before mounting, seems its not empty, exiting" >> /tmp/log.txt exit 1 fi fi /bin/mkdir -p /mnt/$UNIQUENAME #echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: mounting usb stick to: /mnt/$UNIQUENAME" >> /tmp/log.txt /bin/mount $PARTITION /mnt/$UNIQUENAME if [[ $? != 0 ]] ; then echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: EEEEE could not mount usb sticks new filesystem, exiting." >> /tmp/log.txt exit 1 fi #echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: copying files to usb stick $UNIQUENAME" >> /tmp/log.txt /bin/cp -r /stuff/to/copy/on/stick/* /mnt/$UNIQUENAME/ if [[ $? != 0 ]] ; then echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: EEEEE could not copy files, exiting." >> /tmp/log.txt && exit 1 exit 1 fi /bin/sleep 10 #/bin/umount $PARTITION || echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: EEEEE could not remount usb stick, exiting." >> /tmp/log.txt ; exit 1 #echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: remounting and checksumming usb stick $UNIQUENAME...." >> /tmp/log.txt /bin/mount -o remount $PARTITION /mnt/$UNIQUENAME if [[ $? != 0 ]] ; then echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: EEEEE could not remount $PARTITION to /mnt/$UNIQUENAME, exiting" >> /tmp/log.txt && exit 1 exit 1 fi echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: checksum of usb stick $UNIQUENAME is $(md5deep -rbs /mnt/$UNIQUENAME | sort | md5sum)" >> /tmp/log.txt /bin/sleep 10 /bin/umount $PARTITION if [[ $? != 0 ]] ; then echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: EEEEE could not unmount usb stick, exiting." >> /tmp/log.txt exit 1 fi /bin/rmdir "/mnt/$UNIQUENAME" if [[ $? != 0 ]] ; then echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: EEEEE could not delete /mnt/$UNIQUENAME after checksumming, seems its not empty, exiting." >> /tmp/log.txt exit 1 fi echo "$(date +%Y%m%d-%H:%M:%S): $UNIQUENAME: done." >> /tmp/log.txt /bin/rm $LOCKFILE /usr/bin/logger "done setting up USB stick $UNIQUENAME" } &

Now grab some USB hubs, plug in as many USB sticks as you can and see how things in /stuff/to/copy/on/stick/ are replicated to all the USB sticks.

Oh, you know what's most important? DISABLE THE SCRIPT WHEN YOU'RE DONE! I missed that part and ruined a colleague's USB-stick after he had started using it for stuff other than the conference's proceeedings :(

No comments:

Post a Comment