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

joe*_*dle 115 logging stdout init.d start-stop-daemon

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

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON $DAEMON_ARGS
Run Code Online (Sandbox Code Playgroud)

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

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

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

小智 122

要扩展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"
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这是一个比@ypocat更好的解决方案,主要是因为将`--start`替换为`--stop`实际上可以正常工作,从而再次关闭守护进程. (2认同)
  • 附带的“start-stop-daemon --test (...)”是什么样子的? (2认同)
  • @MattClimbs它会在每次启动后覆盖该文件.使用`>>`而不是`>`来追加. (2认同)
  • 在您(因为我)因为您的日志为空之前吓坏了之前,请注意这是缓冲的!您可以使用"exec stdbuf -oL -eL $ DAEMON $ DAEMONARGS> $ LOGFILE 2>&1"强制输出刷新每一行(来自https://blog.lanyonm.org/articles/2015/01/11/raspberry -pi-init-script-python.html) (2认同)

you*_*ayy 47

你需要这样做:

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"
Run Code Online (Sandbox Code Playgroud)

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

  • @ypocat我刚刚验证它适用于-c"exec $ DAEMON ...".这意味着不需要pkill黑客攻击. (12认同)
  • 不利的一面......停止服务会杀死bash,但不会启动子进程bash!(就我而言,DAEMON =咖啡). (8认同)
  • 很高兴知道,也有'pkill`解决方案.想知道什么会``-c'执行$ DAEMON ......"`(添加"exec").现在不要在盘子上有这个,所以不能尝试. (5认同)

Sté*_*ane 40

--no-close在开始start-stop-daemon捕获守护程序输出时,您似乎应该能够立即使用该参数.从Debian版本1.16.5开始,这个新功能dpkg包中提供:

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

这使调用者能够查看进程消息以进行调试,或者能够将文件描述符重定向到日志文件,syslog或类似文件.

  • 很遗憾它在Ubuntu 12.04中不可用:( (8认同)
  • @stantonk您是否也将stdout/stderr传输到文件中?完整的命令行如下所示.并确保用户$ USER可以写入日志文件:start-stop-daemon --start --chuid $ USER --pidfile $ PIDFILE --background --no-close --make-pidfile --exec $ DAEMON - $ DAEMONARGS >> /var/log/xxxxx.log 2>&1 (2认同)

lit*_*ude 11

随着OpenRC的(这是在Gentoo或例如高山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
Run Code Online (Sandbox Code Playgroud)


Onl*_*job 8

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

start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas $DAEMON --no-close \
  -- $DAEMON_ARGS >> $LOGFILE 2>&1
Run Code Online (Sandbox Code Playgroud)

然而,这种解决方案可能不是最理想的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"""
Run Code Online (Sandbox Code Playgroud)

要使它工作我们需要在收到终止其子女的包装SIGTERMstart-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"""
Run Code Online (Sandbox Code Playgroud)

注意:uid=65534是用户nobody.

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

守护进程:
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"""
Run Code Online (Sandbox Code Playgroud)

优点:3点的过程(监事daemon,su和守护程序本身).
缺点:$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}'
Run Code Online (Sandbox Code Playgroud)

优点:3个处理(主管pipexec,logger和守护程序本身); 如果守护程序立即终止(例如无效命令),则status_of_proc -p $PIDFILE "$DAEMON" "$NAME"正确报告失败.
缺点:没有.

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


小智 6

通常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
Run Code Online (Sandbox Code Playgroud)