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

Ale*_*ner 37 ubuntu upstart

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

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

小智 36

此代码段将您的服务输出通过管道传输到记录器中,同时仍允许您执行服务进程(从而替换 shell 进程),以便新贵不会感到困惑。它还确保记录器进程重新指向 init,因此它不是您服务的子项,并且它避免将 cruft 留在文件系统中,即使它需要临时创建一个 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
Run Code Online (Sandbox Code Playgroud)

这是它的工作原理:

  1. mkfifo /tmp/myservice-log-fifo简单地制作 fifo 特殊文件(又名命名管道)。键入man 7 fifo以获取更多信息。
  2. ( logger ... </tmp/myservice-log-fifo & ) 在后台从 fifo 开始记录器读取。parens 导致 logger 进程重新成为 init 的父进程,而不是保持当前 shell 进程的子进程。
  3. exec >/tmp/myservice-log-fifo将当前 shell 的 stdout 重定向到 fifo。现在我们有一个用于该 fifo 的打开文件描述符,我们实际上不再需要文件系统条目......
  4. rm /tmp/myservice-log-fifo 所以我们会删除它。
  5. exec myservice 2>/dev/null只需以通常的方式运行服务。标准输出已经进入先进先出,并且在新程序执行时不会改变。

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


Wil*_*lem 32

对于最近的 Ubuntu 版本 (12.04+),只需使用

console log
Run Code Online (Sandbox Code Playgroud)

守护程序输出(STDOUT & STDERR)将被附加到 /var/log/upstart/<service>.log

http://upstart.ubuntu.com/cookbook/#console-log

  • 这将是干净和漂亮的,但不幸的是它在 CentOS 6.x 上不起作用,它仍然提供不支持此功能的旧版 upstart。 (2认同)

Pet*_*nce 11

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

例如

console output
exec /my/script | logger
Run Code Online (Sandbox Code Playgroud)

将登录到 /var/log/messages

例如

console output
exec /my/script | logger -t my-script
Run Code Online (Sandbox Code Playgroud)

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

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

(我使用的是基于 Centos 5.x 的 Amazon Linux AMI;YMMV)

  • 事实证明这不是一个好的解决方案。upstart 锁定在 `logger` 的 PID 上,而不是你真正想要它管理的进程。 (4认同)

小智 10

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

它还具有使logger进程作为 的子进程挂起的不幸副作用init,因此有关谁“拥有”记录器的信息丢失了,任何尚未意识到mkfifo它的人可能会认为这是一个可以被杀死的悬空进程。

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

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

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

myservice 
 \_ bash -c exec 1> >(logger -t myservice) 2>&1 && exec myservice
    \_ logger -t myservice
Run Code Online (Sandbox Code Playgroud)

出于某种原因,上述命令必须包含在bash -c. 我认为这是因为 Upstart 只是假装通过 Bash 运行您的脚本,但实际上并非如此。如果有人可以提出一种避免额外 bash shell 的方法,那就太棒了。


Jor*_*gas 6

这是丑陋的,但迄今为止我发现的最好的

exec /path/to/server >> /tmp/upstart.log 2>&1

  • 当涉及到日志轮换时,该解决方案并不是一个好的解决方案,因为应用程序直接记录到文件中。通过系统日志记录可以避免相关问题。 (2认同)