Alex Reisner Asked: 2010-02-18 15:25:54 +0800 CST2010-02-18 15:25:54 +0800 CST 2010-02-18 15:25:54 +0800 CST 使用 Upstart 记录守护进程的输出 772 我有一个自定义守护进程,由我的 Ubuntu 服务器上的 upstart 管理。除了我需要捕获(记录)守护程序的输出之外,它工作得很好。官方节页面说我可以用来执行此console logged操作,但它记录到什么文件? 我也读过那不再是一个有效的console logged节。我目前使用的是 0.3.9 (Hardy),但会在几个月后升级到 0.6.x (Lucid)。如果实际上不适用于更高版本,我应该使用什么来代替?console logged ubuntu upstart 7 个回答 Voted Keith Rarick 2011-09-29T16:56:27+08:002011-09-29T16:56:27+08:00 此代码段会将您的服务的输出通过管道传输到记录器中,同时仍允许您执行服务进程(从而替换 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 以下是它的工作原理: mkfifo /tmp/myservice-log-fifo只需制作 fifo 特殊文件(又名命名管道)。键入man 7 fifo以获取更多信息。 ( logger ... </tmp/myservice-log-fifo & ) 在后台开始从 fifo 读取记录器。括号导致 logger 进程重新成为 init 的父进程,而不是保持当前 shell 进程的子进程。 exec >/tmp/myservice-log-fifo将当前 shell 的标准输出重定向到 fifo。现在我们有一个用于该fifo的打开文件描述符,我们实际上不再需要文件系统条目...... rm /tmp/myservice-log-fifo所以我们会删除它。 exec myservice 2>/dev/null只需以通常的方式运行服务。Stdout 已经进入 fifo,并且在新程序执行时不会改变。 更新: set -e不需要,因为 Upstart 默认使用此选项运行脚本(请参阅 http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh) Willem 2015-01-14T09:05:43+08:002015-01-14T09:05:43+08:00 对于最近的 Ubuntu 版本(12.04+),只需使用 console log 并且守护程序输出(STDOUT 和 STDERR)将附加到/var/log/upstart/<service>.log http://upstart.ubuntu.com/cookbook/#console-log Peter Mounce 2012-06-21T04:43:23+08:002012-06-21T04:43:23+08:00 如果您使用该console output 节,然后将脚本的输出通过管道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) Alexander Staubo 2015-02-12T19:17:28+08:002015-02-12T19:17:28+08:00 我没有得到mkfifo令人满意的工作技巧。它似乎没有捕获标准错误,并且尝试重定向导致 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 这使用了将 stdout 和 stderr 重定向到命令的技巧。由于我们在bash命令中执行了服务,这具有替换 shell 并神奇地使 bash 成为服务的子进程的副作用,如下所示ps aufxw: myservice \_ bash -c exec 1> >(logger -t myservice) 2>&1 && exec myservice \_ logger -t myservice 由于某种原因,上述命令必须包装在bash -c. 我认为这是因为 Upstart 只是假装通过 Bash 运行您的脚本,但实际上并非如此。如果有人可以提出一种避免额外 bash shell 的方法,那就太好了。 Jorge Vargas 2010-03-17T01:22:38+08:002010-03-17T01:22:38+08:00 这很难看,但到目前为止我发现的最好的 执行 /path/to/server >> /tmp/upstart.log 2>&1 Nikratio 2010-04-02T13:30:23+08:002010-04-02T13:30:23+08:00 您还可以将输出重定向到 syslog,例如 exec $SERVER 2>&1 | logger -t myservice -p local0.info 但是,管道可能会导致新贵将日志记录进程的 PID 与守护进程的 PID 混淆。 perl 2016-12-17T05:17:39+08:002016-12-17T05:17:39+08:00 另一种选择是使用 tee 像: exec $SERVER 2>&1 | tee /dev/stderr | logger -t myservice 获取新贵文件和系统日志输出
此代码段会将您的服务的输出通过管道传输到记录器中,同时仍允许您执行服务进程(从而替换 shell 进程),这样新贵就不会感到困惑。它还确保记录器进程被重新设置为 init,因此它不是您服务的子进程,并且它避免在文件系统中留下杂乱无章的东西,即使它需要临时创建一个 fifo。
以下是它的工作原理:
mkfifo /tmp/myservice-log-fifo
只需制作 fifo 特殊文件(又名命名管道)。键入man 7 fifo
以获取更多信息。( logger ... </tmp/myservice-log-fifo & )
在后台开始从 fifo 读取记录器。括号导致 logger 进程重新成为 init 的父进程,而不是保持当前 shell 进程的子进程。exec >/tmp/myservice-log-fifo
将当前 shell 的标准输出重定向到 fifo。现在我们有一个用于该fifo的打开文件描述符,我们实际上不再需要文件系统条目......rm /tmp/myservice-log-fifo
所以我们会删除它。exec myservice 2>/dev/null
只需以通常的方式运行服务。Stdout 已经进入 fifo,并且在新程序执行时不会改变。更新:
set -e
不需要,因为 Upstart 默认使用此选项运行脚本(请参阅 http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh)对于最近的 Ubuntu 版本(12.04+),只需使用
并且守护程序输出(STDOUT 和 STDERR)将附加到
/var/log/upstart/<service>.log
http://upstart.ubuntu.com/cookbook/#console-log
如果您使用该
console output
节,然后将脚本的输出通过管道logger
传输到(到 syslog(3) 系统日志模块的 shell 命令接口),那么这将起作用。例如
将登录到
/var/log/messages
例如
将登录
/var/log/messages
并标记每条消息my-script
logger --help
记录器使用选项。(我使用的是基于 Centos 5.x 的 Amazon Linux AMI;YMMV)
我没有得到
mkfifo
令人满意的工作技巧。它似乎没有捕获标准错误,并且尝试重定向导致 Upstart 保释而没有错误。它还有一个不幸的副作用,就是让该
logger
进程作为 的子进程到处闲逛init
,因此有关谁“拥有”该记录器的信息丢失了,任何不知道它的人都mkfifo
可能认为这是一个可以被杀死的悬空进程。相反,我最终得到了以下解决方案,它解决了所有这些问题。它导致
logger
成为子进程,同时将服务保留为根进程。不幸的是,它需要 exec'ingbash
,但它看起来很脏。这使用了将 stdout 和 stderr 重定向到命令的技巧。由于我们在
bash
命令中执行了服务,这具有替换 shell 并神奇地使 bash 成为服务的子进程的副作用,如下所示ps aufxw
:由于某种原因,上述命令必须包装在
bash -c
. 我认为这是因为 Upstart 只是假装通过 Bash 运行您的脚本,但实际上并非如此。如果有人可以提出一种避免额外 bash shell 的方法,那就太好了。这很难看,但到目前为止我发现的最好的
执行 /path/to/server >> /tmp/upstart.log 2>&1
您还可以将输出重定向到 syslog,例如
但是,管道可能会导致新贵将日志记录进程的 PID 与守护进程的 PID 混淆。
另一种选择是使用 tee 像:
获取新贵文件和系统日志输出