Systemd conditionals possible

Hi all,

Let me start off by saying the following:

  1. This isn’t a problem with Manjaro. Or anything but my brain/understanding, really.
  2. So if it’s not correctly placed, feel free to move it.

I am trying to create a systemd timer unit to create daily backups for me. Currently, it’s not automatic but I want to change it. The last time I setup automatic anything on Linux, I used a cron job, and while that is still an option, I know the other, perhaps even better option is systemd timer units. So I’m trying to do it that way. But I’m sort of stumped.

The command I use for it, in the terminal is basically in the following format:

<rclone command to run> && <notify-send command for succeess> || <kdialog command for error>

This way I can keep tabs on it. Maybe even hold a log of what happened. But that’s not why I’m asking for assistance.

My reason is that I’m constantly getting error when from the .service file part of the timer unit. The error:

Jun 27 13:25:09 Mirdarthos-PC systemd[1]: /etc/systemd/system/backup-keepass.service:7: Ignoring unknown escape sequences: "/usr/bin/rclone copy --copy-links /mnt/5T/Mirdarthos'\ Stuff/Documents/KeePass Database Onedrive:unencryptedData/KeepassXC\ Dat>
Jun 27 13:25:09 Mirdarthos-PC systemd[1]: /etc/systemd/system/backup-keepass.service:7: Executable name contains special characters: /usr/bin/rclone copy --copy-links /mnt/5T/Mirdarthos'\ Stuff/Documents/KeePass Database Onedrive:unencryptedData/Keepa>
Jun 27 13:25:09 Mirdarthos-PC systemd[1]: backup-keepass.service: Unit configuration has fatal error, unit will not be started.

Or:

Jun 27 13:25:43 Mirdarthos-PC systemd[1]: /etc/systemd/system/backup-keepass.service:6: Ignoring unknown escape sequences: "/mnt/5T/Mirdarthos'\ Stuff/Documents/KeePass"
Jun 27 13:25:43 Mirdarthos-PC systemd[1]: /etc/systemd/system/backup-keepass.service:6: Ignoring unknown escape sequences: "Onedrive:unencryptedData/KeepassXC\ Database/"
Jun 27 13:25:43 Mirdarthos-PC systemd[1]: /etc/systemd/system/backup-keepass.service:6: Ignoring unknown escape sequences: "Copy of \<b\>\<i\>KeepassXC database, unencrypted\<\/i\>\<\/b\> successfully finished."
Jun 27 13:25:43 Mirdarthos-PC systemd[1]: /etc/systemd/system/backup-keepass.service:6: Ignoring unknown escape sequences: "--msgbox=There was an error copying the \<b\>\<i\>KeepassXC database, unencrypted\<\/i\>\<\/b\>."

Or

Jun 27 13:15:15 Mirdarthos-PC systemd[1]: /etc/systemd/system/backup-keepass.service:6: Unbalanced quoting, ignoring: "/usr/bin/rclone copy --copy-links /mnt/5T/Mirdarthos' Stuff/Documents/KeePass Database Onedrive:unencryptedData/KeepassXC Database/ >
Jun 27 13:15:15 Mirdarthos-PC systemd[1]: backup-keepass.service: Unit configuration has fatal error, unit will not be started.

My /etc/systemd/system/backup-keepass.service file:

[Unit]
Description=Backup KeepassXC database to Microsoft Onedrive.

[Service]
Type=simple
ExecStart=/usr/bin/rclone copy --copy-links /mnt/5T/Mirdarthos\'\ Stuff/Documents/KeePass Database Onedrive:unencryptedData/KeepassXC\ Database/ && kdialog --title 'Rclone copy: Onedrive cloud backup' --passivepopup 'Copy of \<b\>\<i\>KeepassXC database, unencrypted\<\/i\>\<\/b\> successfully finished.' 5 || kdialog --ok-label='OK' --msgbox='There was an error copying the \<b\>\<i\>KeepassXC database, unencrypted\<\/i\>\<\/b\>.'

Don’t worry, this KeepassXC database is quite safe behind a strong password and a key file.

At first I thought it might be escaping, so I escaped all paths with \ where there was a special/funny character. But it still wasn’t working. After quite a bit of hair-pulling, I’ve come to the conclusion that it’s because of the conditionals in the ExecStart decleration.

So I’m considering changing it tto a OneShot service with multiple ExecStart declerations.

But, and this is what I want to ask, I’m having trouble fineding out if there can be Conditional ExecStart declerations. Execute a command depending if the command was successful and another command if not. And if so, how to do it? I can create a bash script for thiss, but I don’t really know if that’s the proper way of doing something that is so relatively simple.

Any advice?

1 Like

Try systemd-escape to generate proper paths for systemd units eg.:

$ systemd-escape --path "/mnt/5T/Mirdarthos' Stuff/Documents/KeePass" 
mnt-5T-Mirdarthos\x27\x20Stuff-Documents-KeePass
1 Like

When running systemd units - create a script for the task an call the script - and don’t put interaction into the script - like msgboxes or the like. Use echo message as this will be printed to the journal - then check the journal.

For this usecase - a user backup job - don’t use the system location - create as a user timer/service in ~/.config/systemd

You can find a user service implementation in

3 Likes

Thanks. I was looking for this, but couldn’t find it. What I’m wondering now, does the timer run when the user isn’t logged on to the computer?

Depends if you enabled linger for this user.

Also expect kdialog erroring with ~“no display found”. You probably need to set some env vars, ie. Environment=DISPLAY=:0

FYI, there is also notify-send.

EDIT: Another thing, you can run those commands with ExecStart=/bin/bash -c "command && command2 ||..."

No - the timer is only active when the user is.

if is always the same path, we can add this path as condition

[unit]
...
ConditionDirectoryNotEmpty=/my_source/
# run only if destination is ??
ConditionPathExists=/mnt/5T/Mirdarthos/xxxxxxxxx
...

in ExecStart=, we can call a personal script. it’s always more simple :wink:
example…

if [ ! -d "/mnt/5T/Mirdarthos/xxxxxx" ]; then
    echo "Oups, no destination available" | systemd-cat -t backup -p err
    exit 1
endif
# and/or others tests

echo "start..." | systemd-cat -t backup -p 5

/bin/rclone copy ...
return_code=$?

if [ $return_code -ne 0 ]; then
    echo "ERROR $return_code with rclone command" | systemd-cat -t backup -p err
else
    echo "Backup rclone Ok" | systemd-cat -t backup -p 5
fi
...

After we can consult logs : journalctl -t backup

avril 12 15:09:34 tower backup[7291]: Oups, no destination available
avril 17 15:13:08 tower backup[7462]: Oups, no destination available
avril 18 15:36:34 tower backup[8376]: start…
avril 18 15:36:35 tower backup[8827]: ERROR 10 with rclone command
avril 21 15:54:26 tower backup[8939]: start…
avril 21 15:56:31 tower backup[8999]: Backup rclone Ok

Thank you!

What would you recommend as the best storage location for custom global scripts?

That’s what I suspected. It’s also the reason that I chose it globally and not a user. I want it to do a backup even if I’m not active at my PC. (Although, that wouldn’t happen a lot, I’d like to rather have it set up this way.)

Just in case.

I’m using /usr/local/bin for those.

1 Like

Me too, glad it’s good then! :relieved:

Just in case of use, I think that if you specify User= on a system service you can run as the specified user but independent of user logins.

I’ll look into it, thanks!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.