udev affects behavior of script, prevents dpkg from working

2

I have a udev rule configured to run a shell script whenever a USB flash drive is inserted; I've verified that udev matches against the rule, that the shell script runs as intended when run manually with the correct parameter, and that the script is being run; it successfully mounts the drive and gets to the point where dpkg should be run, but nothing is actually installed.

Also frustrating my efforts is that I have both dpkg and the script itself set to redirect their output to temp files so I can debug this; however, while both display their output perfectly when run manually, they produce completely empty files when triggered by udev, so I can't even see what error dpkg might be producing, if it's making one at all. I've heard that udev doesn't run things with a terminal, but I don't know if that's the case or if that would cause this.

udev rule:

SUBSYSTEMS=="usb", KERNEL=="sd?1", RUN+="/usr/local/sbin/updater-runner.sh %"

Script being run directly by udev:

#!/bin/sh

/usr/local/sbin/updater.sh ${1} & > /tmp/updater.out`

Main script:

#!/bin/sh

DEVICE=$1
echo "Running..."
echo $DEVICE
# check input
if [ -z "$DEVICE" ]; then
    exit 1
fi

# test that the device isn't already mounted
device_is_mounted=`grep ${DEVICE} /etc/mtab`
if [ -n "$device_is_mounted" ]; then
    echo "error: seems /dev/${DEVICE} is already mounted"
fi

# pull in useful variables from vol_id, quote everything Just In Case
# eval `blkid /dev/${DEVICE} -o value | sed 's/^/export /; s/=/="/; s/$/"/'`

ID_FS_LABEL=$(blkid /dev/${DEVICE} -o value | head -n 1)
export ID_FS_LABEL
ID_FS_TYPE=$(blkid /dev/${DEVICE} -o value | tail -n 1)
export ID_FS_TYPE
echo $ID_FS_LABEL
echo $ID_FS_TYPE
if [ -z "$ID_FS_LABEL" ] || [ -z "$ID_FS_TYPE" ]; then
    echo "error: ID_FS_LABEL is empty! did vol_id break? tried /dev/${DEVICE}"
    exit 1
fi

# test mountpoint - it shouldn't exist
if [ ! -e "/media/${ID_FS_LABEL}" ]; then
    # make the mountpoint
    mkdir "/media/${ID_FS_LABEL}"

    # mount the device

    case "$ID_FS_TYPE" in

        vfat) mount -t vfat -o sync,noatime,uid=1000 /dev/${DEVICE} "/media/${ID_FS_LABEL}"
            ;;

        ntfs) mount -t auto -o sync,noatime,uid=1000,locale=en_US.UTF-8 /dev/${DEVICE} "/media/${ID_FS_LABEL}"
            ;;

        ext*) mount -t auto -o sync,noatime /dev/${DEVICE} "/media/${ID_FS_LABEL}"
            ;;
    esac

    #check if file exists

    #run dpkg
    if [ -f "/media/${ID_FS_LABEL}/ACS.deb" ]; then
        echo "Killing ACS..."
        killall ACS
        echo "Running dpkg..."
        yes | dpkg --force-architecture --force-depends -i "/media/${ID_FS_LABEL}/ACS.deb" > /tmp/dpkg.out
        echo "Restarting ACS..."
        nohup ACS &> /dev/null &
    fi
fi

exit 0

tacoman

Posted 2013-03-27T17:08:44.050

Reputation: 23

Answers

0

Not sure about the rest of it but the reason you are getting empty files is that you have a syntax error in your script:

#!/bin/sh

/usr/local/sbin/updater.sh ${1} & > /tmp/updater.out`

should be (you should also capture STDERR):

#!/bin/sh

/usr/local/sbin/updater.sh ${1} > /tmp/updater.out 2>/tmp/updater.error &

The way you have it, the script is put in the background before any output is generated and you get empty files. Also, I assume the ` at the end of the line is a typo right?

As for the rest, what user is this being run as? I don't know enough about udev to guess. Does whoever the script is run as have the rights to execute dpkg?

terdon

Posted 2013-03-27T17:08:44.050

Reputation: 45 216

udev runs everything as root, so far as I know; mount is working, for example. And the tilde is a typo, not sure how it got in there. – tacoman – 2013-03-27T18:50:19.847

@MaxGene yes I imagined it did but I thought I'd ask in case it runs as some other kind of privileged user. The main error was not the the but the&`. If you change it to what I suggested you should at least get some informative error messages and be able to debug it. – terdon – 2013-03-27T18:52:58.843

@MaxGene shot in the dark here, but if you are mounting a VFAT drive you might not be entering the if loop because VFAT is not case sensitive. Not sure if/how that would affect you but since you are giving a specific file name, that might be a problem. Try changing the if [-f to something like if [ $(find /media/${ID_FS_LABEL}/ -iname ACS.deb) ] – terdon – 2013-03-27T18:57:37.877

It actually works perfectly now; I can't post an answer to my own question to supplement yours yet, but the other issue (as I discovered after getting my output redirection fixed) was that udev tampers with PATH somehow, resulting in dpkg balking; setting and exporting my own path from the script worked. – tacoman – 2013-03-27T19:41:39.670

@MaxGene Ah, nice. You can and indeed should post an answer to your own question. That is actively encouraged on the SE sites. I would recommend you unaccept my answer, upvote it for good measure since it did help you out and then post an answer explaining how you fixed it and accept that one.

– terdon – 2013-03-27T19:50:00.230

Unfortunately SE restricts posting an answer within too short of a time, or from upvoting until you get 15 reputation. Else I would have done both. – tacoman – 2013-03-28T11:40:26.283