I have a shell script that runs a clamav scan on a folder on my arch linux system and is supposed to email the results. Here's the code:

/usr/bin/clamscan -r -i /path/to/folder | /usr/bin/mailx -A gmail -s "Clam Scan Results $(/usr/bin/date +%F)" address@gmail.com

The above one-liner works fine if run on the bash command line and I confirmed that the account configured in /etc/mailrc works and email is received. But I want it to run on a schedule and I setup a systemd service unit to call a script called ~/bin/virusscan.sh and a systemd timer unit to trigger it at 2 AM every night. The mailx piece after the pipe is always reporting ... email not sent

Is there a significant difference in how SystemD executes the script?


Description=Daily virus scan




Description=Execute virus scan daily at 2 AM

OnCalendar=*-*-* 02:00:00


Then I can run the service imediatelly to test with:

sudo systemctl start virusscan 

And the status of the service while running is the following:

virusscan.service - Daily virus scan
   Loaded: loaded (/usr/lib/systemd/system/virusscan.service; disabled; vendor preset: disabled)
   Active: active (running) since Tue 2016-10-04 11:54:39 PDT; 11s ago
 Main PID: 29915 (virusscan.sh)
    Tasks: 4 (limit: 4915)
   CGroup: /system.slice/virusscan.service
           ├─29915 /bin/sh /home/username/bin/virusscan.sh
           ├─29920 /usr/bin/clamscan -r -i /path/to/folder/
           └─29921 /usr/bin/mailx -A gmail -s Clam Scan Results 2016-10-04 address@gmail.com

Oct 04 11:54:39 hurricane systemd[1]: Started Daily virus scan.

It looks like SystemD breaks the one liner in the script into separate processes and also it expands the string that is supposed to be the subject line of the message and removes the quotes ... That could be the problem, perhaps, and I just need to escape it properly ... Then when the service unit is done running, I always have the following line at the end ...

Oct 04 11:55:01 hurricane virusscan.sh[29915]: ... message not sent
  • 1
    systemd is a pig (sorry). Wouldn't it be easier to set it up as a cron job? – gogoud Oct 4 '16 at 21:11
  • @gogoud Yes ... I am beginning to realize that. I was just trying to follow the tutorials on the recommended way to do it for Arch systems. I can make this work with a hand tied behind my back using cron ... – λ Jonas Gorauskas Oct 5 '16 at 1:52

According to Arch Wiki mailx forks and systemd kills the main process when script exits. Looks like adding -v to mailx call prevents it from forking, but more correct way to make it work with systemd is to add -Ssendwait to mailx's arguments.

| improve this answer | |

There are some benefits to using systemd timers vs cron in terms of handling the logging for you and nice status reports.

systemd does have a more restrictive $PATH environment setting by default compared to cron.

In your examples, you have specified only complete paths, so it's not immediately clear that this is the problem. However, mailx is likely calling some other binaries it expects to find in the $PATH.

It looks like mailx supports a --debug-level option which you could set to trace7 to get maximal debug output.

| improve this answer | |
  • I will try with debug turned on and report back here later. – λ Jonas Gorauskas Oct 5 '16 at 17:40
  • After much trial and error what finally worked for me was adding high verbosity to the mailx part of the command, like so: /usr/bin/clamscan -r -i /path/to/folder | /usr/bin/mailx -vv -A gmail -s "Clam Scan Results $(/usr/bin/date +%F)" address@gmail.com – λ Jonas Gorauskas Oct 30 '16 at 19:40
  • And once you turned on high verbosity, what the root case that was illuminated? – Mark Stosberg Oct 31 '16 at 0:15

Systemd supports option KillMode, which defaults to control-group. If set to


it won't kill the forked process when script is finished.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.