守护进程调用的前台程序是否应根据严重性级别在 stderr 和 stdout 之间拆分日志记录?

守护进程调用的前台程序是否应根据严重性级别在 stderr 和 stdout 之间拆分日志记录?

通常,日志消息会写入 stderr。我想知道将日志消息拆分为错误和警告以写入 stderr 而将调试/信息/通知消息写入 stdout 是否是一个好主意/做法?或者这是否无关紧要,因为许多专用日志记录过程无论如何都只从 stdin 读取,这需要将 stderr 和 stdout 中的源日志消息合并并重定向到记录器的 stdin。

[更新]

下面的两个答案都提到了 syslog,我想我需要详细澄清设置。

runit我询问的守护进程本身在前台运行。守护进程由诸如或 之类的监督进程管理supervisord。在这两种情况下,守护进程的 stderr 和 stdout 都将由监督进程捕获,而监督进程的工作是决定如何以及在何处存储日志(可能是 syslog,或者通过 UDP 存储在网络中的其他地方)。守护进程不必担心写入什么日志以及在何处写入日志,因为它们只写入 stdout/stderr。

对于runit,其日志记录工具svlogd将从其 stdin 读取重定向的日志消息,这些消息是托管守护进程的 stderr/stdout 的组合。对于supervisord,它可以将 stderr 和 stdout 记录到单独的日志文件中。

因此,在这种特定设置中,将日志在 stderr 和 stdout 之间拆分,还是只写入其中一个,是一种好的做法?

答案1

我不建议将 stdout 和 stderr 混合使用里面你的程序,而是你如何处理它外部由您决定。stdout旨在用于管道的处理数据,而 则stderr专门用于非数据消息。这使得某些行为(例如批处理)成为可能,而不会改变现有的交互行为。您的情况不同 - stdout 很可能毫无意义。

因为runit对通过 进行日志记录的方式略有不同svlog,并且您正在编写的服务很可能不会守护进程(在这种情况下意味着“从 tty 分离”),因此是否要通过脚本将所有内容捕获到单个日志中取决于您/etc/sv/<servicename>/run。在大多数情况下,大多数运行脚本使用

exec 2>&1 

将两个流融合在一起,因为大多数服务不通过 stdout 传递数据。如果您确实想使用,svlog则需要创建一个脚本并/etc/sv/<servicename>/log/run使用适当的命令来启动它。它可能看起来类似(但不完全像)这个:

#!/bin/sh
exec 2>&1
exec svlog -tt main

其中main是指向日志目录的符号链接。

答案2

首先,需要澄清一些重要的事情:一旦守护进程成功启动,STDOUT和就很少与其上下文相关,除非您使用调试开关调用它。STDERR

守护进程的重点在于它需要与控制终端脱离关系,这样它才能在注销后继续存在。一旦没有终端,所有消息都需要发送到 syslog 守护进程或由进程直接管理的日志文件。

如果你实际上并不是指守护进程,而只是指你自己编写的任何 shell 脚本或类似脚本,那么逻辑通常应该是这样的:

  • STDOUT:任何您想要通过管道或基本输出重定向捕获的内容。
  • STDERR:“带外”消息。你无论如何都想让某些消息到达某人的终端,即使他们正在进行某种重定向。(这就是为什么它们与错误相关联)让用户决定是否也想重定向这些消息,即重定向STDERRSTDIN你提到的位置。

答案3

我认为您不应该同时使用 stdout 和 stderr 进行日志记录。如果您有不同严重程度的日志消息,则应使用前缀标记它们,以便于使用 进行过滤/排序svlogd

我认为同时使用 stdout 和 stderr 进行日志记录会违反最小意外原则。

答案4

如果它是守护进程,我建议使用 syslog 接口将您的消息直接记录到日志中。运行“man 3 syslog”获取信息。如有必要,您的程序还可以有一个调试选项(带有指定优先级的参数),告诉守护进程不要在后台运行,并记录到 stderr。

我会编写一个日志函数,以优先级和字符串作为参数。它应该调用 syslog() 来正确记录消息,如果优先级大于或等于全局调试优先级值,则将消息输出到 stderr 以及 syslog()。调用以syslog(..., "%s", msg)避免消息中的百分比字符被搞乱。(或者让您的函数采用可变数量的参数并将参数列表传递给 vsyslog()。)

确保openlog(..., LOG_PID, LOG_DAEMON)在程序初始化时调用。| LOG_PERROR如果处于调试模式,您可以在 LOG_DAEMON 后添加,这样可以避免编写上述日志记录函数。但这样您将失去根据优先级进行过滤的能力。

您可能(如果使用 Ubuntu)需要进行配置/etc/rsyslog.conf以确保守护进程消息被记录。

PS——如果你的守护进程是 shell 脚本,请使用 logger 命令

相关内容