joeytwiddle
joeytwiddle

Reputation: 31285

How can I log the stdout of a process started by start-stop-daemon?

I am using an init script to run a simple process, which is started with:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON $DAEMON_ARGS

The process called $DAEMON usually prints log information to its standard output. As far as I can tell this data is not being stored anywhere.

I would like to write or append the stdout of $DAEMON to a file somewhere.

The only solution I know is to tell start-stop-daemon to call a shellscript instead of $DAEMON directly; the script then calls $DAEMON and writes to the logfile. But that requires an extra script which, like modifying the daemon itself, seems the wrong way to solve such a common task.

Upvotes: 129

Views: 111594

Answers (13)

jurkomp
jurkomp

Reputation: 1

With modern start-stop-daemon it is enough to use:

--background --output /path/to/the/file

Upvotes: 0

Étienne
Étienne

Reputation: 4984

Starting with version 1.20 there is an option --output for doing exactly this.

Upvotes: 1

Zim
Zim

Reputation: 2785

there is an option --no-close for start-stop-daemon, which means "don't close any fd when it's run background."

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON --no-close \
    -- $DAEMON_ARGS > /var/log/some.log 2>&1

this redirect the stdout/stderr of process start-stop-daemon to the file. and your executable inherits stdout/stderr from its parent process start-stop-daemon.

Upvotes: 2

little-dude
little-dude

Reputation: 1674

With openrc (which is the default on gentoo or alpine linux for instance) start-stop-daemon has the -1 and -2 options:

-1, --stdout Redirect stdout to file

-2, --stderr Redirect stderr to file

So you can just write:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON $DAEMON_ARGS -1 $LOGFILE -2 $LOGFILE

Upvotes: 15

Raashid Muhammed
Raashid Muhammed

Reputation: 109

Usually start-stop-daemon closes the standard file descriptors when running in the background. From the man page of start-stop-daemon:

-C, --no-close
Do not close any file descriptor when forcing the daemon into the background. Used for debugging purposes to see the process output, or to redirect file descriptors to log the process output. Only relevant when using --background.

This one worked for me:

    start-stop-daemon -b -C -o -c \ 
         $DAEMON_USER -S -x $DAEMON > $DAEMON_LOG 2>&1

Upvotes: 8

Onlyjob
Onlyjob

Reputation: 5868

It is not too hard to capture daemon's output and save it to file:

start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas $DAEMON --no-close \
  -- $DAEMON_ARGS >> $LOGFILE 2>&1

However this solution may be suboptimal for logrotate.

It might be better to capture output to syslog. On Debian this would match behaviour of systemd services. The following straightforward attempt to rewrite the above example is wrong because it leaves behind two parent-less ("zombie") processes (logger and daemon) after stopping the daemon because start-stop-daemon terminates only its child but not all descendants:

## Do not use this!
start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas /bin/sh \
  -- -c """exec $DAEMON $DAEMON_ARGS | /usr/bin/logger --tag $NAME"""

To make it work we need a wrapper that terminates its children upon receiving SIGTERM from start-stop-daemon. There are some:

duende:
start-stop-daemon --start --background \
  --pidfile $PIDFILE \
  --startas /usr/sbin/duende \
  -- --pid $PIDFILE --chroot=/ --uid 65534 --ident $NAME \
  /bin/su --login $DAEMON_USER --shell /bin/sh --command """exec ${DAEMON} $DAEMON_ARGS"""

Note: uid=65534 is a user nobody.

Pros: it works and it is relatively easy.
Cons: 4 processes (supervisor duende, its fork with dropped privileges (logger), su and daemon itself); mandatory --chroot; If daemon terminates right away (e.g. invalid command) status_of_proc -p $PIDFILE "$DAEMON" "$NAME" report it as started successfully.

daemon:
start-stop-daemon --start --pidfile $PIDFILE \
  --startas /usr/bin/daemon \
  -- --noconfig --name $NAME --stderr=syslog.info --stdout=syslog.info \
  -- /bin/su --login $DAEMON_USER --shell /bin/sh --command """exec $DAEMON $DAEMON_ARGS"""

Pros: 3 processes (supervisor daemon, su and daemon itself).
Cons: Difficult to manage $PIDFILE due to confusing daemon's command line options; If daemon terminates right away (e.g. invalid command) status_of_proc -p $PIDFILE "$DAEMON" "$NAME" report it as started successfully.

pipexec (the winner):

start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas /usr/bin/pipexec -- -k \
   -- [ D $DAEMON $DAEMON_ARGS ] [ L /usr/bin/logger --tag $NAME ] '{D:2>D:1}' '{D:1>L:0}'

Pros: 3 processes (supervisor pipexec, logger and daemon itself); If daemon terminates right away (e.g. invalid command) status_of_proc -p $PIDFILE "$DAEMON" "$NAME" correctly report failure.
Cons: none.

This is the winner -- the easiest, neat solution that seems to be working well.

Upvotes: 10

stormbeta
stormbeta

Reputation: 1564

To expand on ypocat's answer, since it won't let me comment:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
 --make-pidfile --pidfile $PIDFILE --background       \
 --startas /bin/bash -- -c "exec $DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1"

Using exec to run the daemon allows stop to correctly stop the child process instead of just the bash parent.

Using --startas instead of --exec ensures that the process will be correctly detected by its pid and won't erroneously start multiple instances of the daemon if start is called multiple times. Otherwise, start-stop-daemon will look for a /bin/bash process and ignore the actual child process running the daemon.

Upvotes: 144

youurayy
youurayy

Reputation: 1665

You need to do:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec /bin/bash -- -c "$DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1"

Also if you use --chuid or --user, make sure the user can write to /var/log or the existing /var/log/some.log. The best way is to have that user own a /var/log/subdir/ though.

Upvotes: 49

nairbv
nairbv

Reputation: 4323

I'm not sure if "$DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1" will ever close the file descriptor for the log file... which means if your daemon runs forever, I'm not sure that logrotate or other mechanisms for cleaning up disk space would work. Since it's > instead of >>, the suggested command would also truncate existing logs on restart. If you want to see why the daemon crashed, and it restarts automatically, that might not be very helpful.

Another option might be "$DAEMON | logger". logger is a command that will log to syslog (/var/log/messages). If you need stderr too, I think you could use "$DAEMON 1>&2 | logger"

Upvotes: 3

Stéphane
Stéphane

Reputation: 3934

It seems you should be able to use now the --no-close parameter when starting start-stop-daemon to capture the daemon output. This new feature is available in the dpkg package since version 1.16.5 on Debian:

Add new --no-close option to disable closing fds on --background.

This enabled the caller to see process messages for debugging purposes, or to be able to redirect file descriptors to log files, syslog or similar.

Upvotes: 41

jakub.piasecki
jakub.piasecki

Reputation: 556

How about:

sudo -u myuser -i start-stop-daemon ...

Upvotes: 1

joeytwiddle
joeytwiddle

Reputation: 31285

Quoting an old mailing list:

https://lists.ubuntu.com/archives/ubuntu-uk/2005-June/000037.html

An easy -- and if you want to use start-stop-daemon perhaps the only -- way around it is to create a small script containing:

#!/bin/sh
exec /home/boinc/boinc/boinc > /home/boinc/log/boinc.log

and then use that script as the argument to start-stop-daemon.

Perhaps the real question however is whether it is really necessary to use start-stop-daemon in the first place?

Upvotes: 4

paxdiablo
paxdiablo

Reputation: 881403

Assuming it's bash (although some other shells may allow this as well), the line:

exec >>/tmp/myDaemon.log

will send all future standard output to that file. That's because exec without a program name just does some redirection magic. From the bash man page:

If command is not specified, any redirections take effect in the current shell.

Management of said file is another issue of course.

Upvotes: 2

Related Questions