I have been using clamdscan to run checks on selected directories successfully once every week for a wile using crontab but recently I wanted to move to systemd timer instead as mentioned in the wiki I used to set it up.
The date on the logs is really nice and I want to keep that, but here comes the problem.
Usually I am able to figure out escape characters and where I have to use them, but in this case, I just crash into a wall whatever I try.
The timer works perfectly but the service file reports “Ignoring unknown escape sequences” because, yeah, I cant figure out how to do them so the path to the logfile becomes totally whack whatever I try.
My service file WITHOUT any \ added, this is the line that works in cli and crontab (so its easier for you to see what the end result I want to achieve).
[Unit]
Description=Run clamdscan every Sunday at 18:00, started by timer
[Service]
Type=simple
ExecStart=/usr/bin/clamdscan --fdpass --multiscan --move=/home/bedna/.clam/quarantine --log=/home/bedna/.clam/logs/$(date +\%Y-\%m-\%d).log /redacted/path1 /redacted/path2 /redacted/path3 /redacted/path4 2>/dev/null 1>&2
#ExecStop=/usr/bin/notify-send -u normal 'Clamdscan done' "Check ~/.clam/logs/${CLAMDSCAN_TIME}.log for more info"
The ExecStop is disabled at the moment, I was trying to make an environment variable by running ExacStartPre=/usr/bin/systemctl --user set-environment CLAMDSCAN_TIME=$(date +\%Y-\%m-\%d) but with little success, I simply cant figure out what characters to escape or not, it it the + that messes everything up?
Please help.
Edit
The service and timer are at --user level residing in ~/.config/systemd/user if that makes a difference.
This syntax is inspired by shell syntax, but only the meta-characters and expansions described in the following paragraphs are understood, and the expansion of variables is different. (systemd.service)
Write your own script file and let it execute in the ExecStart portion:
Yes, that was always an option, but not an answer to the topic. xD
Or is it simply not possible to get the string to work in a systemd service?
Is it because of the + or something because I use escape characters in other systemd services without problem.
If a scriptfile is the ONLY option I’d rather just stay with crontab.
All I need is a current date in the log name, if there are other ways to achieve this within a systemd service that would also be a solution.
Yeah, that was the first I did, but with " instead of '… hmmmm, now that you mention it…
oh you mean without the escape characters… I have not… give me a sec…
Using: ExecStart=/usr/bin/clamdscan --fdpass --multiscan --move=/home/bedna/.clam/quarantine --log=/home/bedna/.clam/logs/$(date +%Y-%m-%d).log etc etc…
returns: ERROR: Can't access file /home/bedna/+/home/bedna/.config/systemd/user-86d3f4ac45b448848750f60a2402f259-/run/user/1000/credentials/clamdscan.service).log
in journalctl and actually creates a logfile in correct location named “$(date”
I will try with /usr/bin/bash -c but pretty sure it will return exactly the same, it always has before.
Furhtermore, If I escape ONLY the first $ it starts, but the logfile gets very long in the string. it seems the other $ gets data, to translate into the user and the service or something, nothing makes sense to me.
Yeah, the coin dropped the first time you mentioned it. In this case it actually works with both, my idea was to have a variable to use, but since I now don’t, the usage of ’ is good practice.
Yepp, that’s what did it.
Oddly enough % is not mentioned in the link you posted and that is the same manpage I use for systemd, that’s why I couldn’t figure it out…
Final result:
~/.config/systemd/user/clamdscan.timer
[Unit]
Description=Schedule Clamdscan to run every Sunday at 18.00
[Timer]
Persistent=true
OnCalendar=Sun *-*-* 18:00:00
[Install]
WantedBy=timers.target
~/.config/systemd/user/clamdscan.service
[Unit]
Description=Run clamdscan every Sunday at 18:00, started by timer
[Service]
Type=simple
ExecStart=/usr/bin/bash -c '/usr/bin/clamdscan --fdpass --multiscan --move=/home/bedna/.clam/quarantine --log=/home/bedna/.clam/logs/$(date +%%Y-%%m-%%d).log /redacted/path1/ /redacted/path2/ /redacted/path3/ /redacted/path4/ 2>/dev/null 1>&2'
ExecStop=/usr/bin/notify-send -u normal 'Clamdscan done' 'Check ~/.clam/logs/ for more info'
Yeah… well… It takes about 3-4h to run the scan even if I use +20 cores… xD
It’s ok, the notification works, what I am unsure of is WHEN it will trigger or if at all.
Will it only run after ExecStart is done or will it not run because the script is never actually stopped. Maybe ExecStartPost (or end or what it now was, can’t remember) is what I should use.
I could probably find out pretty easy, I would just make up a dummy service and try but I’m to lazy. I can wait to find out, it’s just a notification.
Edit
Also, you forgot to teach me about how I would need to add an [Install] target section if I want to run the service. Or can I start it anyway, now I’m unsure.
The more I try to read about ExecStartPost the more confused I get, It’s not really mentioned in man pages, not sure it will actually work, maybe I’ll do some testing.
But 2 other ways should work since its nested with bash.
add && exit 0 and then add the notify-send to ExecStop
add && notify-send blahblahblah after in the same ExecStart as clamdscan.
It would accomplish that the ExecStop would be triggered when clamdscan is done.
I have been looking everywhere for that man page, I simply cant find it.
But I have seen similar explanations on other pages like stack exchange and such.
But it does NOT seem to be what I’m looking for, doesn’t “invoke” mean “started” in this case?
I want the notification when clamdscan is DONE.
I know, kinda what I said.
What I do not know though is if I can START it, or if it simply means I can’t enable it.
Yeeeeeah, that would need to be like 3-4HOURS then. Edit
Oh ■■■■■my dyslexia kicked in, I see what you are saying now. Yeah, I might do that, or wait a until Sunday and see what happens… xD
I think my solutions are better tbh, either calling ExecStop with an exit or simply adding it with a && because how I interpret ExecStartPost is that it will start directly AFTER clamdscan has successfully started, not finished.
Could be used for a notification that clamdscan has successfully started to scan, but that I can hear on my fans. xD
Another really handy specifier to use in user-units is %h
For that functionality just add another ExecStartafter the command you want to be performed before it, they are invoked/executed in sequence. (after each other on success of the previous one)
[Service]
ExecStart=clamdscan --fdpass --multiscan --move=%h/.clam/quarantine /redacted/path1/ /redacted/path2/ /redacted/path3/ /redacted/path4/
ExecStart=notify-send -u normal -w -i data-information -a "Clamdscan" 'Done, check for more info:' "journalctl --user --unit %N"
No need for separate log files, because the stdout output is saved in the journal logs…
No need to use absolute paths when the utils are located in the system path, eg. /usr/bin etc…
It is preferred to use absolute paths, but it’s not needed in certain cases, hence it is not new…
man systemd.exec
PATHS
The following settings may be used to change a service’s view of the filesystem. Please note that the paths must be absolute and must not contain a “…”
path component.
ExecSearchPath=
Takes a colon separated list of absolute paths relative to which the executable used by the Exec*= (e.g. ExecStart=, ExecStop=, etc.) properties can
be found. ExecSearchPath= overrides $PATH if $PATH is not supplied by the user through Environment=, EnvironmentFile= or PassEnvironment=. Assigning
an empty string removes previous assignments and setting ExecSearchPath= to a value multiple times will append to the previous setting.
Environment Variables Set or Propagated by the Service Manager
The following environment variables are propagated by the service manager or generated internally for each invoked process:
$PATH
Colon-separated list of directories to use when launching executables. systemd uses a fixed value of
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin" in the system manager. When compiled for systems with "unmerged /usr/" (/bin is not a symlink to
/usr/bin), ":/sbin:/bin" is appended. In case of the user manager, a different path may be configured by the distribution. It is recommended to not
rely on the order of entries, and have only one program with a given name in $PATH.
But then again i could be wrong Try and see the magic…
It is not required anymore. It is still recommend to use a full path.
However systemd does not use the same $PATH as your interactive shell. The folders used to check for a binary are set fixed on compilation time.