Script run from udev rule gets killed shortly after start

Hi everyone.
I’ve written a udev rule to backup data in a usb stick when plugged in (that is backup data FROM usb to HDD).
Before updating to 12.3 the script worked fine. I can’t recall if something else came in the way, but after updating the script gets killed shortly after starting. The device mounts, rsync starts and the detached script gets killed killing rsync and leaving the device mounted.

Any pointers as to what might be going wrong?

The rule is:

KERNEL=="sd?1", ACTION=="add", SUBSYSTEMS=="scsi", ATTRS{vendor}=="JetFlash", ATTRS{model}=="Transcend 4GB   ", RUN+="/usr/local/bin/backupUSB.sh %k"

The script is:

#!/bin/bash
{
    # Log beggining of backup
    /usr/bin/logger USB Backup - Beginning at `date`
    # if needed, create the mount directory
    if  ! -d /mnt/backup ] ; then mkdir /mnt/backup ; fi


    /bin/mount -t vfat -o shortname=mixed,iocharset=utf8 /dev/$1 /mnt/backup


    # Backup command using RSync
    rsync -avh --progress --modify-window=2 /mnt/backup/** /home/diggy/backups/TrancendBackup/ > /tmp/usblog.txt


    # force sync of files to disk before unmounting
    /bin/sync


    # unmount the backup disk
    /bin/umount /mnt/backup


    # Log end of backup
    /usr/bin/logger USB Backup - End at `date`
} &

Does the log file contain any useful errors? I note that you mount the device, then rsync immediately afterwards. I wonder if a small delay is required to guarantee the operation?

That won’t work. RUN is for short program invocations only and udev enforces this. Also, it would have been killed by systemd anyway when parent udev exits.

The clean way to do it using modern systemd/udev infrastructure.

  1. Create systemd service that starts you backup script on request. Do not put it in background! I.e. remove { … } & wrapper. Otherwise system will believe your script finished as soon as it is started:
bor@opensuse:~> cat > /etc/systemd/system/backup\@.service << EOF
[Unit]
Description=Backup to USB Flash Disk
BindsTo=dev-%i.device

[Service]
Type=simple
ExecStart=/usr/local/bin/backupUSB.sh %I
EOF
bor@opensuse:~> systemctl daemon-reload

This is template unit (it has “@” in its name). Later you will dynamically instantiate template by calling it with device name. You refer to device name using %i and %I placeholders (latter is capital “i” not small “L”). BindsTo ensure service is stopped when device in unplugged.

  1. Create udev rule to start service when device in plugged in.
bor@opensuse:~> cat > /etc/udev/rules.d/99-backup.rules << EOF
KERNEL=="sd?1", ACTION=="add", SUBSYSTEMS=="scsi", ATTRS{vendor}=="JetFlash", ATTRS{model}=="Transcend 4GB   ", RUN+="/usr/bin/systemctl --no-block start backup@%k.service"
EOF
bor@opensuse:~> udevadm control --reload

Now when you plug in USB stick service backup@sdX1.service should be started. You can check status using “systemctl status backup@sdX1.service”.

Nice answer arvidjaar. Many backup methods rely on the former udev/script strategy, so others are bound to fall into this trap too. I will remember this post for future reference.

Yes, very illuminating example on how to use systemd/udev.

First of all thank you all for your prompt replies.

@deano_ferrari
Thanks for the interest. No errors or info in the log whatsoever.

@arvidjaar](https://forums.opensuse.org/members/arvidjaar.html)
SOOO elegant solution. I didn’t have any idea I could make it work with systemd.
Works as promised!
Two questions though:

  1. When plugging in the device, it mounted instantly in KDE and unmounted before I the service starts. No major issue here. In the other hand the device still is available for mount in KDE. Haven’t tried it but I’m assuming that trying to mount while the backup service runs will fail, right?

  2. I want to have a visual indication as to when the backup starts (so as not to try to mount it) and ends (so that I can mount and use it). I found someone used notify-send setting the missing DBUS_SESSION_BUS_ADDRESS env here: Ubuntu: backup to USB drive on mount | Ninetynine.be

Would you say this is a lean way to do it or should I find some other way?

Thank you in advance.

I understand that it is mounted, [size=2]but I’m surprised it is unmounted, I do not know who does it.
[/size]

[size=2][size=2][FONT=book antiqua][size=2]No major issue here. In the other hand the device still is available for mount in KDE. Haven’t tried it but I’m assuming that trying to mount while the backup service runs will fail, right?[/size][/size][/size][/FONT]
[size=2][size=2]
[/size]
As your script mounts dev[size=2]ice, I expect[size=2] [size=2]udisks[size=2] (and[size=2] user session disk managers using it) will notice that fact and won’t offer to mount partition again. You can also prevent automount by setting [size=2]ENV{UDISKS_AUTO}=“0” or set it to be completely ignored by setting ENV{UDISKS_IGNORE}=“1” device property in udev rule. I assume KDE in 12.3 finally switched to using udisks2.[/size][/size][/size][/size][/size][/size]

  1. I want to have a visual indication as to when the backup starts (so as not to try to mount it) and ends (so that I can mount and use it). I found someone used notify-send setting the missing DBUS_SESSION_BUS_ADDRESS env here: Ubuntu: backup to USB drive on mount | Ninetynine.be

Would you say this is a lean way to do it or should I find some other way?
[/size]
I guess it will work. Unfortunately this is the same problem as with running X11 program outside of user context - you need to know DBUS session address (X11 DISPLAY number) before you can try to communicate. The clean way is to have some small program started in user session and listening on system bus for signals and forwarding them to local session notification manager. Signals are broadcast to all users so sending program does not really need to know how many listeners there are nor their address. But solution described in the link will do as well as long as you need to notify only one and the same user always.

Worked like a charm.
Now I have my rsync based backup working fine and with KDE notifications in place.

Thank you!