37

I'm having trouble piping the STDOUT & STDERR to a file when running a program as a systemd service. I've tried adding the following to the .service file:

ExecStart=/apppath/appname > /filepath/filename 2>&1

But this doesn't work. The output is ending up in /var/log/messages and is viewable using journalctl but I'd like a separate file.

I've also tried setting StdOutput=tty but can't find a way of redirecting this to a file.

Any help would be appreciated.

mattdm
  • 2,082
  • 25
  • 39
MichaelB76
  • 640
  • 1
  • 6
  • 15

2 Answers2

51

systemd.service(5) says:

ExecStart=

Commands with their arguments that are executed when this service is started.

So, systemd runs your /apppath/appname with args >, /filepath/filename, 2>&1

Try:

ExecStart=/bin/sh -c '/apppath/appname > /filepath/filename 2>&1'
Community
  • 1
  • 1
  • 1
    Thanks. That helped but the underlying problem I was having turned out to be with SELinux silently blocking writes to the logging folder I was trying to use. – MichaelB76 Nov 13 '15 at 15:55
  • 12
    Some might want to replace the first > with >> to append to the log file. – Yvo May 12 '16 at 04:00
  • 4
    To note - this will spawn two processes, one for the shell wrapper and one for appname. To kill both processes with 'systemctl stop appname', use pkill in ExecStop. ExecStop=/bin/pkill -TERM -P $MAILPID – siliconrockstar May 25 '16 at 23:26
  • 2
    @siliconrockstar see https://www.freedesktop.org/software/systemd/man/systemd.kill.html#KillMode= –  May 26 '16 at 01:02
  • ^ Yeah I just learned that, you can set KillMode=control-group to kill all the processes, without having to kill all processes in ExecStop or ExecReload. – siliconrockstar May 26 '16 at 17:40
  • 16
    You can use `exec` to replace shell with the target process. By using this, you will get rid of need for killing 2 procs with KillMode or whatever. `ExecStart=/bin/bash -c 'exec /usr/local/bin/service &>> /var/log/service.log'` – mighq Mar 23 '17 at 13:31
  • This problem is just another reason why i loathe `systemd`. – sjas Jun 19 '17 at 12:52
6

Try:

ExecStart=/usr/bin/sh -c "/apppath/appname > /filepath/filename 2>&1"

ExecStart requires the first argument to be a binary (no exceptions), and doesn't allow pipes or redirection. Therefore, use ExecStart to start a shell within which you can do all the fancy things required.

Casey
  • 490
  • 7
  • 11