如何记录start-stop-daemon启动的进程的stdout?

时间:2011-11-24 03:33:25

标签: logging stdout init.d start-stop-daemon

我使用init脚本来运行一个简单的过程,该过程以:

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

名为$ DAEMON的进程通常会将日志信息打印到其标准输出。据我所知,这些数据没有存储在任何地方。

我想将$ DAEMON的stdout写入或附加到某个文件中。

我知道的唯一解决方案是告诉start-stop-daemon直接调用一个shellscript而不是$ DAEMON;然后脚本调用$ DAEMON并写入日志文件。但这需要一个额外的脚本,就像修改守护进程本身一样,似乎是解决这种常见任务的错误方法。

11 个答案:

答案 0 :(得分:117)

要扩展ypocat的答案,因为它不会让我发表评论:

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"

使用exec运行守护程序允许stop正确停止子进程,而不仅仅是bash parent。

使用--startas代替--exec可确保其pid正确检测进程,并且如果多次调用start,则不会错误地启动守护程序的多个实例。否则,start-stop-daemon将查找/ bin / bash进程并忽略运行守护进程的实际子进程。

答案 1 :(得分:45)

你需要这样做:

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"

此外,如果您使用--chuid--user,请确保用户可以写信至/var/log或现有/var/log/some.log。最好的方法是让该用户拥有/var/log/subdir/

答案 2 :(得分:40)

在启动--no-close以捕获守护程序输出时,您现在应该能够使用start-stop-daemon参数。从版本1.16.5开始,dpkg包中的new feature可用于Debian:

  

添加新的--no-close选项以禁用--background上的关闭fds。

     

这使调用者能够查看用于调试的进程消息   目的,或者能够将文件描述符重定向到日志文件,   系统日志或类似的。

答案 3 :(得分:11)

使用openrc(例如gentoo或alpine linux的默认设置)start-stop-daemon-1-2选项:

  

-1, - stdout将stdout重定向到文件

     

-2, - stderr将stderr重定向到文件

所以你可以写:

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

答案 4 :(得分:8)

捕获守护程序的输出并将其保存到文件中并不太难:

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

然而,对于logrotate,此解决方案可能不是最理想的。

将输出捕获到syslog可能更好。在Debian上,这将匹配systemd服务的行为。 以下直接尝试重写上面的示例是错误,因为它在停止守护进程后留下了两个无父(“僵尸”)进程(logger和守护进程),因为start-stop-daemon仅终止它孩子,但不是所有的后代:

## 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"""

为了使其有效,我们需要一个包装器,在从SIGTERM收到start-stop-daemon后终止其子级。有一些:

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"""

注意:uid=65534是用户nobody

优点:它有效且相对容易 缺点:4个进程(主管duende,其分支具有已删除的权限(记录器),su和守护进程本身);强制--chroot; 如果守护程序立即终止(例如无效命令)status_of_proc -p $PIDFILE "$DAEMON" "$NAME"将其报告为已成功启动。

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"""

优点:3个进程(主管daemonsu和守护进程本身)。
缺点:由于混淆守护程序的命令行选项而难以管理$PIDFILE; 如果守护程序立即终止(例如无效命令)status_of_proc -p $PIDFILE "$DAEMON" "$NAME"将其报告为已成功启动。

pipexec获胜者):

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}'

优点:3个进程(主管pipexeclogger和守护进程本身);如果守护程序立即终止(例如无效命令)status_of_proc -p $PIDFILE "$DAEMON" "$NAME"正确报告失败 缺点:无。

这是赢家 - 最简单,最简洁的解决方案似乎运作良好。

答案 5 :(得分:5)

通常start-stop-daemon在后​​台运行时关闭标准文件描述符。 来自start-stop-daemon的手册页:

  

-C, - no-close
   强制守护程序进入后台时,请勿关闭任何文件描述符。用于调试目的看                 进程输出,或重定向文件描述符以记录进程输出。仅在使用--background时才相关。

这个对我有用:

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

答案 6 :(得分:4)

引用旧邮件列表:

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

  

一个简单的 - 如果你想使用start-stop-daemon也许唯一的方式   围绕它创建一个包含以下内容的小脚本:

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

然后使用该脚本作为start-stop-daemon的参数。

     

然而,真正的问题可能是它是否真的有必要使用   start-stop-daemon首先在哪里?

答案 7 :(得分:3)

我不确定“$ DAEMON $ DAEMON_ARGS> /var/log/some.log 2>& 1”是否会关闭日志文件的文件描述符...这意味着如果你的守护进程永远运行,我不确定logrotate或其他清理磁盘空间的机制是否有效。因为它是>而不是>>,建议的命令也会在重启时截断现有日志。如果你想知道守护进程崩溃的原因,并且它会自动重启,那可能不是很有帮助。

另一种选择可能是“$ DAEMON | logger”。 logger是一个将记录到syslog(/ var / log / messages)的命令。如果你也需要stderr,我想你可以使用“$ DAEMON 1>& 2 | logger”

答案 8 :(得分:2)

假设它是bash(尽管其他一些shell也允许这样做),行:

exec >>/tmp/myDaemon.log

将所有未来的标准输出发送到该文件。这是因为没有程序名称的exec只会做一些重定向魔术。从bash手册页:

  

如果未指定command,则任何重定向都会在当前shell中生效。

管理上述文件当然是另一个问题。

答案 9 :(得分:2)

--no-close有一个选项start-stop-daemon,表示“在后台运行时不要关闭任何fd”。

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

这会将进程start-stop-daemon的标准输出/标准错误重定向到文件。并且您的可执行文件会从其父进程start-stop-daemon继承stdout / stderr。

答案 10 :(得分:1)

怎么样:

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