Running automatic photo download script when camera is mounted

For many years I was using a bash script to retrieve photos from my camera in Ubuntu. I used to start the script with a shortcut on the desktop whenever the camera was mounted. The script ran with root permissions, mounted the camera, downloaded pictures and videos, unmounted it, and opened my preferred photo viewer – gthumb. Today I added a simple user dialog to the script and made it start automatically when the camera is mounted.

The script

/etc/asterisk.scripts/download_and_prepare_Nex.sh

#!/bin/bash
#script downloads all photos from camera into a time based directory under /all/photos
#then creates a mail version for each photo, and runs X11_APP
#20130724 - modified for Nex
#20161001 - modified as systemd service call

UUID=9016-4EF8
X11_APP=/usr/bin/gthumb
mnt=/media/asteri/$UUID

logger Running Sony Nex download script

function end {
  umount /dev/disk/by-uuid/$UUID || notify "Sony NEX: Camera was NOT unmounted"
  #or: umount $mnt  
  exit
}

function notify {
  notify-send "$1"
}

if [ ! -e "$mnt/DCIM" ]; then
 notify "Sony NEX: Camera photos not found"
 end
fi

#allow user to cancel the script (remove later)
xmessage -center -buttons Yes:0,No:1 -default Yes -nearmouse "Copy photos from Sony NEX camera?" -timeout 100 || end

choice="$?"

if [[ "$choice" == 1 ]]; then
  end
fi

notify "Sony NEX: started copying photos and videos"

#create new date/time based directory to hold the photos
photoDir=/all/photos/new_nex_`date +%Y%m%d_%H%M%S`

#create the diretory and copy files over
mkdir $photoDir
cd $photoDir
cp $mnt/DCIM/100MSDCF/* $photoDir
cp $mnt/DCIM/101MSDCF/* $photoDir
cp $mnt/DCIM/102MSDCF/* $photoDir
cp $mnt/DCIM/103MSDCF/* $photoDir
cp $mnt/PRIVATE/AVCHD/BDMV/STREAM/* $photoDir

#convert file names to lowercase (don't you hate uppercase file names?)
sudo rename 'y/A-Z/a-z/' *

#create mail size photos and optimize them (optional)
for i in *.jpg; do convert -scale 978x650 -quality 85% $i mail_$i; done
for i in mail*.jpg; do jhead -autorot -dc -dt -de $i; done

#change ownership from root
chown -R asteri:asteri $photoDir

#run photo viewer
${X11_APP} $photoDir &

#ask user whether to delete the photos from camera (optional)
xmessage -center -buttons Yes:0,No:1 -default Yes -nearmouse "Sony NEX: copy done, delete all photos from camera?" -timeout 100

choice="$?"

if [[ "$choice" == 0 ]]; then
    rm $mnt/DCIM/100MSDCF/*
    rm $mnt/DCIM/101MSDCF/*
    rm $mnt/DCIM/102MSDCF/*
    rm $mnt/DCIM/103MSDCF/*
    rm $mnt/PRIVATE/AVCHD/BDMV/STREAM/*
    notify "Sony NEX: all done, photos cleaned, you can disconnect the camera"
else
    notify "Sony NEX: all done, photos left in camera"
fi

end

Run the script when camera is mounted

Ubuntu already auto-mounts my USB devices (using udisks), so I did not have to set-up fstab or udev. Once mounted, there are several ways to automatically start a script:

  • Use Ubuntu’s Removable Media preferences. This option is not device specific, but could be made so in the script file.
  • Create a udev rule. Scripts can be added to udev rules either using a RUN key or using ENV SYSTEMD_WANTS directive to trigger a systemd service.
  • Create a systemd service (without udev rules) and connect it to the device mount event

The third option was new to me and I wanted to try it out. First, I needed the mount name of my camera:

asteri@master:~$ sudo systemctl list-units -t mount
UNIT                            LOAD   ACTIVE SUB     DESCRIPTION
-.mount                         loaded active mounted /
boot-efi.mount                  loaded active mounted /boot/efi
boot.mount                      loaded active mounted /boot
dev-hugepages.mount             loaded active mounted Huge Pages File System
dev-mqueue.mount                loaded active mounted POSIX Message Queue File System
media-asteri-9016\x2d4EF8.mount loaded active mounted /media/asteri/9016-4EF8
...

Then I created the systemd service (which I named sonynex), under /etc/systemd/system/sonynex.service, and connected it to the script path and the mount point found earlier:

[Unit]
Description=Get photos from Sony NEX camera
Requires=media-asteri-9016\x2d4EF8.mount
After=media-asteri-9016\x2d4EF8.mount

[Service]
Environment="DISPLAY=:0" "XAUTHORITY=/home/asteri/.Xauthority"
ExecStart=/etc/asterisk.scripts/download_and_prepare_Nex.sh

[Install]
WantedBy=media-asteri-9016\x2d4EF8.mount

Note that in my script I experimented with user dialogs in X, for which I had to set the Environment’s DISPLAY and XAUTHORITY in the systemd service file.

The last step was to enable the new service:

asteri@master:~$ sudo systemctl enable sonynex.service

This command’s output showed a suspicious path, the dash character in the service name was not translated into \x2d when transformed into a name of systemd’s wants directory:

Created symlink from /etc/systemd/system/media-asteri-9016x2d4EF8.mount.wants/sonynex.service to /etc/systemd/system/sonynex.service.

I believe this is a bug in systemctl. I could rename the device name, but renaming the generated directory was simpler:

cd /etc/systemd/system/
sudo mv media-asteri-9016x2d4EF8.mount.wants "media-asteri-9016\x2d4EF8.mount.wants"

After that I reloaded systemctl to pick up my changes:

systemctl daemon-reload

… and the script fires as expected.

 

Resources:

Leave a Reply

Your email address will not be published. Required fields are marked *