1

I would like to setup a Raspberry Pi 3 running Rasbian to automatically copy a DVD disk when a disk is inserted in a coupled disk station. To achieve this, I have written a udevrule and a script to run when this rule is triggered.

The udev rule seems to work fine and runs the script when the disk is inserted.

The script contains the dd command. When i execute the script manually from the command line, it works correctly and executes the ddcommand. When the script is run by udev on disk insertion however, everthing in the script executes, except the dd command.

I have searched online but could not find anyone else with the same issue. Does someone have a clue what the problem might be?

udev rule /etc/udev/rules.d/65-autorip.rules:

SUBSYSTEM=="block", KERNEL=="sr[0-4]", ACTION=="change", RUN+="/usr/local/bin/autorip/autorip.sh /dev/%k %E{ID_CDROM_MEDIA}"

disk copy script /usr/local/bin/autorip/autorip.sh:

#!/bin/bash

# function to activate a led and eject disk when an error occurs
error(){
    python /usr/local/bin/autorip/led-on.py
    eject
}

# function to deactivate the led for
reset_led(){
    python /usr/local/bin/autorip/led-off.py
}

# if udev flag to check if disk change action is insert (second script parameter) is set
if [ $2 == "1" ]; then
    reset_led
    #use wodim command to find out if disk is DVD
    disk_info=$(wodim -atip dev='/dev/sr0')
    if [[ $disk_info = *"mmc_mdvd"* ]] ; then
            # copy disk contents to temp location (not working when ran from udev)
            dd if=/dev/sr0 of=/tmp/autorip_disk_image_$RANDOM$RANDOM.iso
            eject
    else
            error
    fi
fi

2 Answers2

3

udev rules are not meant for longer running tasks, like copying a DVD. From man udev:

This can only be used for very short-running foreground tasks. Running an event process for a long period of time may block all further events for this or a dependent device.

Starting daemons or other long-running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished.

In addition, scripts executed by udev run in a somewhat restricted environment.

So the proper way to do this is to make an udev rule that triggers a program that was already started by the user (via D-Bus, a socket, a named pipe, or otherwise); this program can then in turn copy the DVD. This also solves the problem of giving the DVD-copying program proper permissions.

Hauke Laging
  • 90,279
dirkt
  • 32,309
  • But you could use it to start systemd units. They are not forked from the process which causes the start. – Hauke Laging Apr 16 '18 at 19:21
  • @HaukeLaging: Yes, any way to communicate with another program (systemd, at, socat with exec, whatever) and have it start something is fine. – dirkt Apr 16 '18 at 19:29
  • socat does not isolate processes. – Hauke Laging Apr 16 '18 at 19:44
  • @HaukeLaging: It doesn't have to - the socat with the exec option isn't forked from the udev process, it's started beforehand. The udev process can use a second socat without exec to message the first socat, of course. Or it can use something else. – dirkt Apr 16 '18 at 19:54
  • @HaukeLaging Thank you for your answer. This was the information I needed to continue my project! – Arne Van Den Kerchove Apr 17 '18 at 17:10
0

When a script or program doesn't do what you think it should do it's time to get out the debugging tools. In the script, add the following two lines at the top to record what it is doing:

set -x
exec >/tmp/debug-$$.out 2>&1

Then it will write a log of every command executed to a debug file in the /tmp/ directory. My wild guess is that you will see that the script not only does not execute dd but also the eject command in the next line, because the wodim command does not see the DVD at the time the script is run by udev. That can probably be fixed by adding a sufficient sleep before the wodim.