How to Pipe Output to a File When Running as a Systemd Service?

33,992

Solution 1

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'

Solution 2

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.

Share:
33,992
MichaelB76
Author by

MichaelB76

Updated on February 22, 2020

Comments

  • MichaelB76
    MichaelB76 about 4 years

    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.

  • MichaelB76
    MichaelB76 over 8 years
    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.
  • Yvo
    Yvo almost 8 years
    Some might want to replace the first > with >> to append to the log file.
  • siliconrockstar
    siliconrockstar almost 8 years
    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
  • Admin
    Admin almost 8 years
  • siliconrockstar
    siliconrockstar almost 8 years
    ^ 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.
  • mighq
    mighq about 7 years
    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'
  • sjas
    sjas almost 7 years
    This problem is just another reason why i loathe systemd.