使用Upstart记录守护进程的输出


34

我有一个自定义守护程序,该守护程序由Ubuntu服务器上的upstart管理。它非常完美,除了我需要捕获(记录)守护程序的输出。该负责人节页说,我可以使用console logged要做到这一点,但什么文件,它记录到?

我也读了console logged不再有效的节。我目前使用的是0.3.9(Hardy),但会在几个月内升级到0.6.x(Lucid)。如果console logged实际上无法在更高版本上使用,我该怎么用呢?


1
您是否可以简单地更新自定义守护程序以将输出发送到syslog或该守护程序的配置文件中指定的日志文件?
Zoredache

Answers:


35

此代码片段会将服务的输出通过管道传送到logger,同时仍允许您执行服务进程(从而替换了shell进程),从而不会混淆新贵。它还可以确保记录器进程已重新绑定到init,因此它不是您的服务的子项,并且即使需要临时创建fifo,也避免了文件系统中的混乱现象。

script
  mkfifo /tmp/myservice-log-fifo
  ( logger -t myservice </tmp/myservice-log-fifo & )
  exec >/tmp/myservice-log-fifo
  rm /tmp/myservice-log-fifo
  exec myservice 2>/dev/null
end script

运作方式如下:

  1. mkfifo /tmp/myservice-log-fifo只需制作fifo特殊文件(也称为管道)即可。键入man 7 fifo更多信息。
  2. ( logger ... </tmp/myservice-log-fifo & ) 从后台开始从fifo读取记录器。括号使记录器进程重新初始化为init,而不是保留当前shell进程的子进程。
  3. exec >/tmp/myservice-log-fifo将当前shell的标准输出重定向到fifo。现在我们有了该fifo的打开文件描述符,实际上我们不再需要文件系统条目了...
  4. rm /tmp/myservice-log-fifo 因此我们将其删除。
  5. exec myservice 2>/dev/null只需以通常的方式运行服务即可。Stdout已经进入了fifo,并且在执行新程序时不会改变。

UPDATE: set -e不需要,因为Upstart默认使用此选项运行脚本(请参阅 http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh


很好的答案,并且不会在任何地方留下fifo文件。
Ash Berlin-Taylor

什么是set -e
彼得·蒙斯

1
set -e导致脚本,如果任何命令无法立即退出。如果没有该行,脚本将无用(可能会很危险)继续运行后续命令。
基思·拉里克

1
要记录stderr和stdout,请在该行exec 2>&1上方添加rm一行,然后2>/dev/null从最后一行删除。
itsadok


11

如果使用console output stanza,然后将脚本的输出通过管道logger传输到(syslog(3)系统日志模块的shell命令界面),那么它将起作用。

例如

console output
exec /my/script | logger

将登录到 /var/log/messages

例如

console output
exec /my/script | logger -t my-script

将登录/var/log/messages并标记每个消息my-script

logger --help 记录器使用选项。

(我在基于Centos 5.x的Amazon Linux AMI上; YMMV)


4
事实证明,这不是一个好的解决方案。新贵将锁存到的PID logger,而不是您实际希望其管理的进程的PID 。
彼得·蒙斯

10

我没有获得mkfifo令人满意的工作技巧。它似乎没有捕获到stderr,并且尝试重定向导致Upstart保释,没有错误。

不幸的是,使该logger过程作为的子进程徘徊也有不利的副作用init,因此有关谁“拥有”记录器的信息会丢失,并且任何尚未意识到这种mkfifo可能的人都可能认为这是一个悬而未决的过程,可以将其杀死。

相反,我最终得到了以下解决方案,该解决方案解决了所有这些问题。它导致logger 成为子进程,同时将服务保留为根进程。不幸的是,它需要执行bash,但是看起来很脏。

script
  # ... setup commands here, e.g. environment, cd, ...
  exec bash <<EOT
    exec 1> >(logger -t myservice) 2>&1
    exec myservice
EOT
end script

这使用了一种将stdout和stderr重定向到命令的技巧。由于我们在bash命令内部执行了服务,因此具有替换外壳和神奇地使bash成为服务的子进程的副作用,如下所示ps aufxw

myservice 
 \_ bash -c exec 1> >(logger -t myservice) 2>&1 && exec myservice
    \_ logger -t myservice

由于某种原因,上面的命令必须包装在一个bash -c。我认为这是因为Upstart仅假装通过Bash运行脚本,而实际上不是。如果有人可以提出一种避免使用额外的bash shell的方法,那将是很棒的。


1
是! 我很高兴发现了这个。看起来比mkfifo变体更好,就我而言,我需要在exec bash -l << EOF那里没有任何损失。
thom_nic 2015年


3

您也可以将输出重定向到syslog,例如

exec $SERVER 2>&1 | logger -t myservice -p local0.info

但是,管道可能会导致新贵将日志记录进程的PID与守护程序的PID混淆。


混淆PID的守护程序实际上是一个无用的守护程序,因为它应该监视该进程,然后重新生成它。关于如何确保监视正确的PID有任何想法吗?
约翰·菲利普·斯特拉特豪森,2012年

我认为(但没有尝试过)您会想要expect forkexpect daemon节。或者cat,我想您也可以将pid文件放入日志消息中。
Peter Mounce 2012年

1

另一种选择是使用tee,例如:

exec $SERVER 2>&1 | tee /dev/stderr | logger -t myservice

获取新贵文件和syslog输出

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.