StandardOutput option of systemd is not working

3

2

I'm using systemd to start a program on boot and keep it running in the background.

I wrote a simple script for systemd to call and the script will print several lines of logs which I'd like to see in the terminal.

So I set StandardOutput=journal+console in the service configuration but I wasn't able to see the outputs neither in the terminal nor the journal.

frederick@Frederick-PC:~$ sudo systemctl start my_program.service
frederick@Frederick-PC:~$ journalctl _SYSTEMD_UNIT=my_program.service
No journal files were found.
-- No entries --

And these are my service configuration and the script.

/etc/systemd/system/my_program.service

[Unit]
Description=Start my_program client after system is booted

[Service]
Type=forking
ExecStart=/usr/bin/my_program.sh start
ExecStop=/usr/bin/my_program.sh stop
PIDFile=/run/my_program.pid
WorkingDirectory=/home/frederick/Applications/my_program-go/
StandardOutput=journal+console

[Install]
WantedBy=multi-user.target

/usr/bin/my_program.sh

#!/bin/sh

start() {
    if [ -f /run/my_program.pid ]; then
        kill -0 $(cat /run/my_program.pid) > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            echo "my_program has been already started"
            exit 1
        fi
    fi
    echo -n "Starting my_program... "
    nohup /home/frederick/Applications/my_program-go/my_program-local -c /home/frederick/Applications/my_program-go/config.json >> /home/frederick/Applications/my_program-go/my_program.log 2>&1 &
    if [ $? -gt 0 ]; then
        echo "failed"
        rm /run/my_program.pid > /dev/null 2>&1
    else
        echo $! | tee /run/my_program.pid
    fi
}

stop() {
    if [ -f /run/my_program.pid ]; then
        echo -n "Stopping my_program... "
        msg=$(kill $(cat /run/my_program.pid) 2>&1)
        if [ $? -gt 0 ]; then
            echo "failed"
            echo $msg
        else
            rm /run/my_program.pid > /dev/null 2>&1
            echo "succeeded"
        fi
    else
        echo "my_program not started"
    fi
}

restart() {
    stop
    start
}

case $1 in
    start|stop|restart)
        "$1"
        ;;
    *)
        echo "No such operation"
        exit 1
        ;;
esac

How can I see those lines printed by echo in the script? Please help, thanks.

Frederick Zhang

Posted 2015-09-01T22:16:22.357

Reputation: 459

Answers

6

I wrote a simple script for systemd to call …

… which was the source of the problem. Your "simple script" overrode where the standard output and standard error were sent. And that entirely unnecessarily. All of the redirection, PID file writing, nohup-ing, and forking is entirely unnecessary for something that is already daemonized and already has its PID known by the service manager. You don't need any part of that script at all. Instead, write your service unit like this:

[Unit]
Description=Start my_program client after system is booted

[Service]
Type=simple
ExecStart=/home/frederick/Applications/my_program-go/my_program-local -c /home/frederick/Applications/my_program-go/config.json
WorkingDirectory=/home/frederick/Applications/my_program-go/
StandardOutput=journal+console

[Install]
WantedBy=multi-user.target

Invoke whatever options are necessary to stop your program from forking, unless it actually definitely implements the forking readiness protocol. Very few programs actually do. Your "simple script" certainly didn't, as it exited the parent process long before the dæmon had initialized and was ready.

Further reading

JdeBP

Posted 2015-09-01T22:16:22.357

Reputation: 23 855

1Your configuration works but it still prints nothing to the console nor the journal. If you run my_program directly in terminal, it will start listening to configured ports and print logs to standard output without daemonization. So what I want in the terminal or journal is not the output by the program itself, but something like Starting... my_program started, Starting... my_program already started. Just something like the traditional init scripts! How can this be achieved? – Frederick Zhang – 2015-09-02T12:34:37.113

The "Wrapping Apache Tomcat in many pointless extra layers" house of horror article is eminently readable and should apply to JBoss/Wildfly too I suppose. – David Tonhofer – 2017-07-13T10:28:38.940