如何记录由start-stop-daemon启动的进程的标准输出?


120

我正在使用一个初始化脚本来运行一个简单的过程,该过程始于:

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

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

我想将$ DAEMON的标准输出写入或附加到某个文件中。

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

Answers:


127

扩展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父进程。

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


2
这比@ypocat主要是因为通过更换再次关闭后台程序下来一个一个更好的解决方案--start--stop实际工作。
2014年

我尝试从rc.local而不是init.d运行此命令...我似乎没有得到相同的结果。但是,当通过SSH从shell运行它时,它就像一个魅力!
nemo 2014年

1
伴随的start-stop-daemon --test (...)样子如何?
阿卜杜勒

2
@MattClimbs每次启动后都会覆盖文件。用于>>代替>附加。
喵喵

2
在因为您的日志为空而疯狂(像我一样)之前,请注意这已被缓冲!可以使用“EXEC stdbuf -oL -El $ $ DAEMON DAEMONARGS> $ LOGFILE 2>&1”强制输出刷新每一行(从blog.lanyonm.org/articles/2015/01/11/...
piers7

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"

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


1
太棒了,谢谢ypocat。今天,除了保存日志外,我还需要运行一个非二进制脚本,该脚本--exec不允许,但是您的技巧可以解决!
joeytwiddle 2012年

8
不利的一面...停止服务会杀死bash,但不会启动子进程bash!(在我的情况下,DAEMON =咖啡)。
joeytwiddle 2012年

1
我通过在do_stop顶部杀死bash进程的所有子进程来解决此问题。 bashPID=$(cat $PIDFILE); [ -n "$bashPID" ] && pkill -P "$bashPID"
joeytwiddle 2012年

5
很高兴知道,pkill解决方案也是如此。想知道会... -c "exec $DAEMON..."做什么(添加“ exec”)。现在不要将其放在盘子上,因此无法尝试。
youurayy 2012年

12
@ypocat我刚刚验证它可以与-c“ exec $ DAEMON ...”一起使用。这意味着不需要任何技巧。
考虑过

40

似乎您现在应该可以--no-close在开始start-stop-daemon捕获守护程序输出时使用该参数。从Debian的1.16.5版本开始,软件包中提供了此新功能dpkg

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

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


8
可惜它在Ubuntu 12.04中不可用:(
Leon Radley

我似乎无法得到-难以接近...输出仍将转到我正在执行init.d脚本的shell中:(
stantonk 2013年

+1通过守护程序node.js服务在Debian压缩上完美工作。
讲者2014年

2
@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
nharrer 2014年

1
openrc无法使用此功能start-stop-daemon。但是,openrc版本具有-1-2选项,分别用于重定向stdout和stderr。
little-dude

14

使用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

9

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

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服务的行为。以下直接重写上面的示例的尝试是错误的,因为在停止守护程序后,它仅留下了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。有一些:

决斗
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"则将其报告为已成功启动。

守护进程
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"正确报告失败。
缺点:无。

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


7

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

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?


3

我不确定“ $ DAEMON $ DAEMON_ARGS> /var/log/some.log 2>&1”是否会关闭日志文件的文件描述符……这意味着您的守护程序是否永远运行,我不确定logrotate或其他清理磁盘空间的机制将起作用。由于它是>而不是>>,因此建议的命令还将在重新启动时截断现有日志。如果您想查看守护程序为何崩溃并自动重新启动的原因,那可能不是很有帮助。

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


没错,使用>>通常更适合于守护程序,尽管这意味着您现在应该创建一个logrotate规则!
joeytwiddle

至于磁盘空间,截断文件的方法将立即获得空间(至少在ext文件系统下)。但是要当心那些只删除仍在写入的文件的方法:在释放句柄之前,不会回收空间,并且您将无法再找到文件节点来手动截断它!
joeytwiddle

我要说的@joeytwiddle部分是,在某些情况下,如果从未关闭文件句柄,则logrotate将无法旋转日志。
nairbv

--no-close ... | logger对我不起作用(Debian 7.3,start-stop-daemon 1.16.12)。尽管/ var / log / messages已填充:-),但start-stop-daemon脚本不会返回。我尝试了有没有1>&2
hgoebl 2014年

hgoebl您需要在引号中使用“ cmd | logger”表达式,因此解释器将知道您正在传递到logger的“ cmd”,而不是start-stop-daemon表达式。
Wexxor

2

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

exec >>/tmp/myDaemon.log

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

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

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


您能否弄清楚应该将这条线放置在何处?在第start-stop-daemon一个问题提到的那一行之后?
阿卜杜勒

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.