You are not logged in.
I want to run a self-written backup script (which works perfectly when executed by hand) automatically every time I plug in and mount my encrypted backup drive.
After some research I found out this is possible via systemd services, so I came up with this:
[Unit]
Description=Triggers backup script when usb backup drive is mounted
RequiresMountsFor=/run/media/xxx/Seagate Backup
[Service]
ExecStart=/home/xxx/backup-home.sh
[Install]
WantedBy=run-media-xxx-Seagate\x20Backup.mount
But for some reason, this doesn't work I want it to. When I start this service via systemctl start, my script will start immediately even when my drive isn't mounted. In this case, I get the following error message on sytemctl status:
[/etc/systemd/system/backup-home.service:3] Failed to add required mount for, ignoring: /run/media/xxx/Seagate Backup
So... where is my error? I already assumed that the space in my device name creates that problem. However, using quotes or using the same format as in WantedBy in RequiredMountsFor doesn't solve the problem.
In case this won't work that way: Is there any other possibility to run a script on device mount? I already know about udev rules, but I read this isn't the optimal solution for backups and similar time-consuming tasks.
Many thanks in advance.
Last edited by brdvlps (2016-01-03 20:56:30)
Offline
Your want:
Requires=media-Seagate\ Backup.mount
After=media-Seagate\ Backup.mount
Or a variant of that will account for spaces in the device name (?)...
Offline
Your want:
Requires=media-Seagate\ Backup.mount After=media-Seagate\ Backup.mount
Or a variant of that will account for spaces in the device name (?)...
RequiresMountsFor=
Takes a space-separated list of absolute paths. Automatically adds dependencies of type Requires= and After= for all mount units required to access the specified path.
Mount points marked with noauto are not mounted automatically and will be ignored for the purposes of this option. If such a mount should be a requirement for this unit, direct dependencies on
the mount units may be added (Requires= and After= or some other combination).
I don't see how ANY of them could work with a udisks mount though. systemd doesn't know how to mount it with udisks like it do for an fstab entry.
WantedBy would work though. I have it working here as a USER unit -- but only when the unit name doesn't have "escaped" characters (e.g. hyphens in UUID, spaces in LABEL).
Last edited by tom.ty89 (2016-01-03 04:17:13)
Offline
That's how I mount mine: but we covered that in the previous thread...
Offline
I just tried
Requires=run-media-xxx-Seagate\x20Backup.mount
After=run-media-xxx-Seagate\x20Backup.mount
(-run-media-xxx-Seagate\x20Backup.mount is the output of systemd-escape "/run/media/xxx/Seagate Backup").
Doesn't work, error message says "failed to add dependency [...], ignoring: Invalid argument" for both lines.
EDIT: Sorry, that was the wrong one. Actually, I got "Failed to start backup-home.service: Unit run-media-xxx-Seagate\x20Backup.mount failed to load: No such file or directory."
I also tried it using only the WantedBy statement, as expected it doesn't work either (without error message).
Any other suggestions?
Last edited by brdvlps (2016-01-03 17:33:45)
Offline
Well if you don't mind, try to change the FILESYSTEM LABEL from "Seagate Backup" to "SeagateBackup" (and change the WantedBy), disable, daemon-reload and enable again, and then remount and see.
Or get in touch with some systemd dev to see how / if it's possible to get it working with those escaped characters.
Last edited by tom.ty89 (2016-01-03 17:45:09)
Offline
I want to run a self-written backup script (which works perfectly when executed by hand) automatically every time I plug in and mount my encrypted backup drive.
After some research I found out this is possible via systemd services, so I came up with this:[Unit] Description=Triggers backup script when usb backup drive is mounted RequiresMountsFor=/run/media/xxx/Seagate Backup [Service] ExecStart=/home/xxx/backup-home.sh [Install] WantedBy=run-media-xxx-Seagate\x20Backup.mount
But for some reason, this doesn't work I want it to. When I start this service via systemctl start, my script will start immediately even when my drive isn't mounted. In this case, I get the following error message on sytemctl status:
[/etc/systemd/system/backup-home.service:3] Failed to add required mount for, ignoring: /run/media/xxx/Seagate Backup
So... where is my error? I already assumed that the space in my device name creates that problem. However, using quotes or using the same format as in WantedBy in RequiredMountsFor doesn't solve the problem.
In case this won't work that way: Is there any other possibility to run a script on device mount? I already know about udev rules, but I read this isn't the optimal solution for backups and similar time-consuming tasks.
Many thanks in advance.
I think the problem is that you need to tell the mount that it needs to start the service, not the other way around. So if there is a systemd unit "run-media-xxx-Seagate\x20Backup.mount" when the device is mounted, you need something like this:
(File: /etc/systemd/system/run-media-xxx-Seagate\x20Backup.mount.d/override.conf)
[Unit]
Wants=yourservice.service
I am using this with devices to have systemd start scripts when I plug in certain USB hardware, but I've tried it with mounts, too.
Offline
I think the problem is that you need to tell the mount that it needs to start the service, not the other way around. So if there is a systemd unit "run-media-xxx-Seagate\x20Backup.mount" when the device is mounted, you need something like this:
(File: /etc/systemd/system/run-media-xxx-Seagate\x20Backup.mount.d/override.conf) [Unit] Wants=yourservice.service
I am using this with devices to have systemd start scripts when I plug in certain USB hardware, but I've tried it with mounts, too.
Thank you! This works perfectly fine for me.
Offline
This does not make sense at all. Wants in an override and a WantedBy with the service enabled should be equivalent. Funny thing is I CANNOT have it working here with Wants, but I CAN with WantedBy.
[tom@localhost ~]$ cd .config/systemd/user/
[tom@localhost user]$ ls
bak default.target.wants escape_broken.service escape.service noescape.service run-media-tom-testloop.mount.d sockets.target.wants
[tom@localhost user]$ cat run-media-tom-testloop.mount.d/override.conf
[Units]
Wants=noescape.service
[tom@localhost user]$ cat noescape.service
[Unit]
Description=Triggers backup script when usb backup drive is mounted
[Service]
ExecStart=/usr/bin/gnome-terminal
[Install]
WantedBy=run-media-tom-testloop.mount
This does not work, but if I do this:
[tom@localhost user]$ systemctl --user enable noescape
Created symlink from /home/tom/.config/systemd/user/run-media-tom-testloop.mount.wants/noescape.service to /home/tom/.config/systemd/user/noescape.service.
It works.
EDIT: nvm, it was the typo in the override ("Units" instead of "Unit"), now both Wants and WantedBy works for me.
Also I found the pitfall on unit with escaped characters:
[tom@localhost ~]$ cd .config/systemd/user/
[tom@localhost user]$ systemctl --user enable escape_broken.service
Created symlink from /home/tom/.config/systemd/user/run-media-tom-testx20loop.mount.wants/escape_broken.service to /home/tom/.config/systemd/user/escape_broken.service.
[tom@localhost user]$ systemctl --user enable escape.service
Created symlink from /home/tom/.config/systemd/user/run-media-tom-test\x20loop.mount.wants/escape.service to /home/tom/.config/systemd/user/escape.service.
[tom@localhost user]$ diff escape_broken.service escape.service
8c8
< WantedBy=run-media-tom-test\x20loop.mount
---
> WantedBy=run-media-tom-test\\x20loop.mount
With double backslash in the WantedBy and hence a proper symlink created when enabling the service, I can have it working on units that have escaped characters too now.
Last edited by tom.ty89 (2016-01-04 04:44:26)
Offline
This does not make sense at all.
I think the reason @brdvlps can have Wants working but not WantedBy is probably because he wasn't aware of the escaping pitfall.
BTW you sure you want a system unit instead of a user unit, especially when the mount is done by udisks?
Last edited by tom.ty89 (2016-01-04 04:53:12)
Offline
Learning something every day...
I've always used the .d drop-in method because I was looking at it under the misunderstanding that "WantedBy=" was only allowed for targets, not services.
So yes, both work (with the extra "\" in one case). Also, a user unit may or may not be better, depending on what exactly you want to back up.
Offline
Or maybe depending on the ownership/permission of the source/target if they are unix filesystems. If they are owned by root, I guess it doesn't matter how you mounted it then :S
Last edited by tom.ty89 (2016-01-04 07:49:30)
Offline
Currently, I back up all the user homes (including /root), so a user unit wouldn't be suitable for this.
Offline
Slightly off topic, even though solved, in case anyone still reads this: Is there any advantange, besides taste or interest, of mounting the device via a unit file as opposed to do so via an udev rule?
Something like:
KERNEL=="sd?" SUBSYSTEM=="block", ENV{ID_SERIAL_SHORT}=="ABC123456789", RUN+="/some/script.sh", OPTIONS+="last_rule"
Where /some/script.sh obviously contains the mount command.
Just wondering about pros ans cons of one way vs. the other
Offline
From http://www.freedesktop.org/software/sys … /udev.html:
RUN{type}
Add a program to the list of programs to be executed after processing all the rules for a specific event, depending on "type":
"program"
Execute an external program specified as the assigned value. If no absolute path is given, the program is expected to live in /usr/lib/udev; otherwise, the absolute path must be specified.
This is the default if no type is specified.
"builtin"As program, but use one of the built-in programs rather than an external one.
The program name and following arguments are separated by spaces. Single quotes can be used to specify arguments with spaces.
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.
Offline
Slightly off topic, even though solved, in case anyone still reads this: Is there any advantange, besides taste or interest, of mounting the device via a unit file as opposed to do so via an udev rule?
Something like:
KERNEL=="sd?" SUBSYSTEM=="block", ENV{ID_SERIAL_SHORT}=="ABC123456789", RUN+="/some/script.sh", OPTIONS+="last_rule"
Where /some/script.sh obviously contains the mount command.
Just wondering about pros ans cons of one way vs. the other
brdvlps pointed out the problem with RUN. Also, I used to use udev for similar cases, but I came to like systemd mainly for two reasons:
1. units can be easily connected (with "Wants", "Requires", "Conflicts" and stuff like that) and extended (with the usr/run/etc .d mechanism).
2. you can do most of this without root access, with systemd user units. All mounts and devices are mapped into user units, so you won't need any root privileges at all for many such tasks.
Offline
First of all thanks for your replies, those seem to be really valid arguments. Now, I've only had time for a quick search so far, so please bear with me, but just in case you have some docs ready or a hint where to start, about how to invoke a certain unit file when a device with a certain serial number is present (or has been added), that would be helpful. So the hotplug/udev event-> unit-file connection is not yet clear to me.
The systemd-udevd page is not a helpful starting point and the arch udev wiki hardly mentions systemd.
Offline
First of all thanks for your replies, those seem to be really valid arguments. Now, I've only had time for a quick search so far, so please bear with me, but just in case you have some docs ready or a hint where to start, about how to invoke a certain unit file when a device with a certain serial number is present (or has been added), that would be helpful. So the hotplug/udev event-> unit-file connection is not yet clear to me.
The systemd-udevd page is not a helpful starting point and the arch udev wiki hardly mentions systemd.
The basic principle is the same as above in the thread: instead of attaching a "Wants" reference to a mount unit, you attach it to a device unit. All USB sticks I know (this means this might not work with all of them!) generate device IDs like "usb-something-serialnumber-something". For example, a Kingston stick I use, when plugged in, shows up in different places, one of them:
/dev/disk/by-id/usb-Kingston_DataTraveler_150_0018F30C08425B93020E0091-0:0
So plug in the USB stick in question and look into /dev/disk/by-id. If there's a link with the serial number, you get your corresponding systemd unit like this:
$ systemctl status /dev/disk/by-id/usb-Kingston_DataTraveler_150_0018F30C08425B93020E0091-0:0
● dev-disk-by\x2did-usb\x2dKingston_DataTraveler_150_0018F30C08425B93020E0091\x2d0:0.device - DataTraveler_150 ANTERGOS
Follow: unit currently follows state of sys-devices-pci0000:00-0000:00:14.0-usb3-3\x2d14-3\x2d14:1.0-host8-target8:0:0-8:0:0:0-block-sdh.device
Loaded: loaded
Active: active (plugged) since Mi 2016-01-06 19:39:39 CET; 8min ago
Device: /sys/devices/pci0000:00/0000:00:14.0/usb3/3-14/3-14:1.0/host8/target8:0:0/8:0:0:0/block/sdh
The first line of output shows you the escaped unit name (you can also get that with the command systemd-escape, btw)
Now you only have to put this device unit name into a "WantedBy" statement of the [Install] section of the service unit you want to activate, and it will be triggered when the usb stick is plugged.
Offline