3 日志文件监控

概述

Zabbix 可用于对日志文件进行集中监控和分析,支持或不支持日志轮转。

当日志文件包含某些字符串或字符串模式时,可以使用通知来提醒用户。

要监控日志文件,您必须具备:

  • 在主机上运行的 Zabbix agent
  • 已配置的日志监控项

被监控日志文件的大小限制取决于 大文件支持

配置

验证 agent 参数

请确保在 agent 配置文件 中:

  • Hostname 参数与前端中的主机名一致。
  • ServerActive 参数中指定了用于处理主动检查的服务器。
监控项配置

配置一个日志监控 监控项

所有必填输入字段都用红色星号标记。

对于日志监控监控项,您需要填写:

类型 在此选择 Zabbix agent (active)
键值 使用以下监控项键值之一:
log[]logrt[]
这两个监控项键值允许监控日志,并根据内容正则表达式(如果存在)过滤日志条目。
例如:log[/var/log/syslog,error]。请确保该文件对 'zabbix' 用户具有读取权限,否则监控项状态将被设置为 'unsupported'。
log.count[]logrt.count[]
这两个监控项键值仅返回匹配行的数量。
有关如何使用这些监控项键值及其参数的详细信息,请参见支持的 Zabbix agent 监控项 键值部分。
信息类型 自动预填:
对于 log[] 或 logrt[] 监控项 - Log
对于 log.count[] 或 logrt.count[] 监控项 - Numeric (unsigned)
如果可选使用 output 参数,您也可以手动选择除 Log 之外的合适信息类型。
请注意,选择非 Log 类型的信息将导致本地时间戳丢失。
更新间隔(秒) 该参数定义 Zabbix agent 检查日志文件是否有变化的频率。将其设置为 1 秒可确保尽快获取新记录。
日志时间格式 在此字段中,您可以可选地指定用于解析日志行时间戳的模式。支持的占位符:
* y: Year (1970-2038)
* M: Month (01-12)
* d: Day (01-31)
* h: Hour (00-23)
* m: Minute (00-59)
* s: Second (00-59)
如果留空,时间戳将被设置为 Unix 时间中的 0,即 1970 年 1 月 1 日。
例如,考虑 Zabbix agent 日志文件中的以下一行:
" 23480:20100328:154718.045 Zabbix agent started. Zabbix 1.8.2 (revision 11211)."
它以 6 个字符位置的 PID 开头,后面是日期、时间以及消息的其余部分。
该行的日志时间格式应为 "pppppp:yyyyMMdd:hhmmss"。
请注意,"p" 和 ":" 字符是占位符,可以是除 "yMdhms" 之外的任何字符。

重要说明

  • 服务器和 agent 会在两个计数器中保留被监控日志的大小和最后修改时间(对于 logrt)。 此外:
    • agent 还会在内部使用 inode 编号(在 UNIX/GNU/Linux 上)、文件索引(在 Microsoft Windows 上)以及前 512 个日志文件字节的 MD5 校验和,以便在日志文件被截断和轮转时改进判断。
    • 在 UNIX/GNU/Linux 系统上,假定存放日志文件的文件系统会报告 inode 编号,这些编号可用于跟踪文件。
    • 在 Microsoft Windows 上,Zabbix agent 会确定日志文件所在的文件系统类型,并使用:
      • 在 NTFS 文件系统上使用 64 位文件索引。
      • 在 ReFS 文件系统上(仅从 Microsoft Windows Server 2012 开始)使用 128 位文件 ID。
      • 在文件索引会变化的文件系统上(例如 FAT32、exFAT),会使用回退算法,以便在日志文件轮转导致多个日志文件具有相同最后修改时间时,在不确定条件下采取合理处理方式。
    • inode 编号、文件索引和 MD5 校验和由 Zabbix agent 在内部收集。 它们不会传输到 Zabbix server,并且在 Zabbix agent 停止时会丢失。
    • 不要修改日志文件的最后修改时间(例如使用 touch),也不要通过将文件复制回其原始名称来替换被监控的日志文件(这会创建新的 inode)。 在这两种情况下,Zabbix 可能会将该文件视为不同的文件,并从头重新读取,这可能会产生重复告警。
    • 如果 logrt[] 监控项存在多个匹配的日志文件,而 Zabbix agent 正在跟踪其中最新的一个,并且这个最新日志文件被删除,则会记录警告信息 "there are no files matching "<regexp mask>" in "<directory>"。 Zabbix agent 会忽略修改时间早于 agent 为正在检查的 logrt[] 监控项所见到的最新修改时间的日志文件。
  • agent 从上次停止的位置开始读取日志文件。
  • 已分析的字节数(大小计数器)和最后修改时间(时间计数器)会存储在 Zabbix 数据库中,并发送给 agent,以确保在 agent 刚启动,或接收到之前被禁用或不受支持的监控项时,agent 会从该位置开始读取日志文件。 不过,如果 agent 从 server 收到了非零的大小计数器,但 logrt[] 或 logrt.count[] 监控项无法找到匹配文件,则大小计数器会重置为 0,以便在文件稍后出现时从头分析。
  • 每当日志文件变得比 agent 已知的日志大小计数器更小时,该计数器会重置为零,agent 会在考虑时间计数器的情况下从文件开头开始读取日志文件。
  • 如果目录中存在多个具有相同最后修改时间的匹配文件,那么 agent 会尝试正确分析所有具有相同修改时间的日志文件,并避免跳过数据或重复分析相同数据,尽管在所有情况下都不能保证。 agent 不会假定任何特定的日志文件轮转方案,也不会自行判断轮转方案。 当出现多个具有相同最后修改时间的日志文件时,agent 会按字典序降序处理它们。 因此,对于某些轮转方案,日志文件将按其原始顺序进行分析和上报。 对于其他轮转方案,则不会遵循原始日志文件顺序,这可能导致匹配到的日志文件记录以不同顺序上报(如果日志文件具有不同的最后修改时间,则不会出现此问题)。
  • Zabbix agent 每隔 Update interval 秒处理一次日志文件的新记录。
  • Zabbix agent 每秒发送的日志文件内容不超过 maxlines。 该限制可防止网络和 CPU 资源过载,并覆盖 agent 配置文件MaxLinesPerSecond 参数提供的默认值。
  • 为了找到所需字符串,Zabbix 会处理比 MaxLinesPerSecond 设置值多 10 倍的新行。 因此,例如,如果 log[]logrt[] 监控项的 Update interval 为 1 秒,默认情况下 agent 最多会分析 200 条日志记录,并且在一次检查中最多向 Zabbix server 发送 20 条匹配记录。 通过在 agent 配置文件中增大 MaxLinesPerSecond,或在监控项键中设置 maxlines 参数,可以将限制提高到一次检查中最多分析 10000 条日志记录,并向 Zabbix server 发送 1000 条匹配记录。 如果 Update interval 设置为 2 秒,则一次检查的限制会比 Update interval 为 1 秒时高 2 倍。
  • 此外,log 和 log.count 值始终限制为 agent 发送缓冲区大小的 50%,即使其中没有非日志值也是如此。 因此,要使 maxlines 值在一次连接中发送(而不是分多次连接),agent BufferSize 参数必须至少为 maxlines x 2。 Zabbix agent 可以在收集日志期间上传数据,从而释放缓冲区;而 Zabbix agent 2 会停止日志收集,直到数据上传并释放缓冲区为止,该过程是异步执行的。
  • 在没有日志监控项的情况下,agent 缓冲区的全部大小都用于非日志值。 当日志值到来时,它们会根据需要替换较旧的非日志值,最多占用指定的 50%。
  • 对于长度超过 256kB 的日志记录,只有前 256kB 会与正则表达式进行匹配,其余记录内容会被忽略。 不过,如果 Zabbix agent 在处理长记录时停止,agent 的内部状态会丢失,并且在 agent 重新启动后,该长记录可能会再次被分析,而且结果可能不同。
  • 关于 "\" 路径分隔符的特别说明:如果 file_format 为 "file\.log",则不应存在 "file" 目录,因为无法明确判断 "." 是被转义了,还是它是文件名的第一个字符。
  • logrt 的正则表达式仅支持文件名,不支持目录正则匹配。
  • 在 UNIX 平台上,如果预期存放日志文件的目录不存在,logrt[] 监控项会变为 NOTSUPPORTED。
  • 在 Microsoft Windows 上,如果目录不存在,该监控项不会变为 NOTSUPPORTED(例如,监控项键中的目录拼写错误时)。
  • logrt[] 监控项缺少日志文件不会使其变为 NOTSUPPORTED。 logrt[] 监控项读取日志文件时发生的错误会作为警告记录到 Zabbix agent 日志文件中,但不会使该监控项变为 NOTSUPPORTED。
  • Zabbix agent 日志文件有助于查明 log[]logrt[] 监控项为何变为 NOTSUPPORTED。 Zabbix 可以监控其 agent 日志文件,但 DebugLevel=4 或 DebugLevel=5 时除外。
  • 使用正则表达式搜索问号,例如 \?,如果文本文件包含 NUL 符号,可能会产生误报,因为 Zabbix 会将这些符号替换为 "?",以继续处理该行直到换行符。

提取正则表达式的匹配部分

有时,当正则表达式匹配成功时,我们可能希望只从目标文件中提取感兴趣的值,而不是返回整行内容。

日志监控项能够从匹配的行中提取所需的值。 这可以通过 loglogrt 监控项中的附加 output 参数来实现。

使用 output 参数可以指定我们可能感兴趣的匹配项中的“捕获组”。

例如:

log[/path/to/the/file,"large result buffer allocation.*Entries: ([0-9]+)",,,,\1]

应当允许返回在以下内容中找到的条目数:

Fr Feb 07 2014 11:07:36.6690 */ Thread Id 1400 (GLEWF) large result
buffer allocation - /Length: 437136/Entries: 5948/Client Ver: >=10/RPC
ID: 41726453/User: AUser/Form: CFG:ServiceLevelAgreement

只会返回数字,因为 \1 指的是第一个也是唯一一个捕获组:([0-9]+)

并且,借助提取并返回数字的能力,该值还可以用于定义触发器。

使用 maxdelay 参数

日志监控项中的 maxdelay 参数允许忽略日志文件中的一些较旧行,以便优先分析在 maxdelay 秒内的最新行。

指定 maxdelay > 0 可能会导致忽略重要的日志文件记录并错过告警。 仅在必要时谨慎使用,并自行承担风险。

默认情况下,用于日志监控的监控项会跟踪日志文件中出现的所有新行。 但是,有些应用在某些情况下会开始向日志文件写入大量消息。 例如,如果数据库或 DNS 服务器不可用,这类应用会向日志文件中刷入成千上万条几乎相同的错误消息,直到恢复正常运行。 默认情况下,所有这些消息都会被认真分析,并且匹配的行会按照 loglogrt 监控项的配置发送到服务器。

内置的过载保护由可配置的 maxlines 参数(防止服务器接收过多匹配的日志行)以及 10*'maxlines' 限制(防止 agent 在一次检查中因过载而使主机 CPU 和 I/O 负载过高)组成。 不过,内置保护仍然存在两个问题。 首先,大量可能并不那么有信息量的消息会被报告到服务器,并占用数据库空间。 其次,由于每秒可分析的行数有限,agent 可能会在数小时内落后于最新的日志记录。 很可能,您更希望尽快获知日志文件中的当前情况,而不是花几个小时去翻阅旧记录。

解决这两个问题的方法就是使用 maxdelay 参数。 如果指定 maxdelay > 0,则在每次检查期间会测量已处理字节数、剩余字节数以及处理时间。 根据这些数值,agent 会计算一个估计延迟 - 即分析日志文件中所有剩余记录所需的秒数。

如果延迟不超过 maxdelay,agent 就会像往常一样继续分析日志文件。

如果延迟大于 maxdelay,agent 就会通过“跳过”日志文件中的一段内容来忽略它,并跳转到一个新的估计位置,以便剩余行能够在 maxdelay 秒内被分析完。

请注意,agent 甚至不会将被忽略的行读入缓冲区,而是会计算在文件中跳转的近似位置。

跳过日志文件行的事实会记录在 agent 日志文件中,如下所示:

14287:20160602:174344.206 item:"logrt["/home/zabbix32/test[0-9].log",ERROR,,1000,,,120.0]"
logfile:"/home/zabbix32/test1.log" skipping 679858 bytes
(from byte 75653115 to byte 76332973) to meet maxdelay

其中 “to byte” 的数值是近似值,因为在“跳转”之后,agent 会将文件中的位置调整到某一日志行的开头,而该位置可能会更靠后或更靠前。

根据日志文件增长速度与分析速度的对比,您可能会看到没有“跳转”、很少或经常“跳转”、大幅或小幅“跳转”,甚至每次检查都会有一次小“跳转”。 系统负载和网络延迟的波动也会影响延迟的计算,因此也会影响为保持跟上 maxdelay 参数而进行的“跳转”。

不建议设置 maxdelay < update interval(这可能会导致频繁的小“跳转”)。

关于处理 'copytruncate' 日志文件轮转的说明

带有 copytruncate 选项的 logrt 假定不同的日志文件包含不同的记录(至少它们的时间戳不同),因此初始块(最多到前 512 字节)的 MD5 校验和也会不同。 如果两个文件的初始块 MD5 校验和相同,则表示其中一个是原始文件,另一个是副本。

带有 copytruncate 选项的 logrt 会尽力正确处理日志文件副本,而不会报告重复项。 但是,不建议出现以下情况:生成多个具有相同时间戳的日志文件副本、日志文件轮转频率高于 logrt[] 监控项更新间隔,以及 agent 频繁重启。 agent 会尽量合理地处理所有这些情况,但无法保证在所有场景下都能获得良好结果。

关于 log*[] 监控项的持久化文件说明

持久化文件的用途

当 Zabbix agent 启动时,它会从 Zabbix 服务器或 proxy 接收一组主动监控项检查。 对于 log*[] 监控项,它会接收已处理的日志大小和修改时间,以便确定从哪里开始监控日志文件。 根据文件系统报告的实际日志文件大小和修改时间,agent 会决定是从已处理的日志大小继续监控日志文件,还是从头重新分析日志文件。

运行中的 agent 会维护一组更大的属性,用于在各次检查之间跟踪所有受监控的日志文件。 当 agent 停止时,这些内存中的状态会丢失。

新的可选参数 persistent_dir 指定一个目录,用于将 log[]、log.count[]、logrt[] 或 logrt.count[] 监控项的状态存储到文件中。 Zabbix agent 重启后,会从持久化文件中恢复 log 监控项的状态。

其主要使用场景是监控位于镜像文件系统上的日志文件。 在某一时刻之前,日志文件会同时写入两个镜像。 随后镜像被拆分。 在活动副本上,日志文件仍在增长,并产生新的记录。 Zabbix agent 会分析这些记录,并将已处理的日志大小和修改时间发送给服务器。 在被动副本上,日志文件保持不变,远远落后于活动副本。 之后,操作系统和 Zabbix agent 会从被动副本重新启动。 Zabbix agent 从服务器接收到的已处理日志大小和修改时间,可能不适用于被动副本上的情况。 为了从文件系统镜像拆分时 agent 停止的位置继续监控日志文件,agent 会从持久化文件中恢复其状态。

带持久文件的 agent 操作

在启动时,Zabbix agent 对持久文件一无所知。只有在从 Zabbix 服务器 (proxy) 收到活动检查列表后,agent 才会发现某些日志监控项应由指定目录下的持久文件提供支持。

在 agent 运行期间,持久文件会以写入方式打开(使用 fopen(filename, "w")),并用最新数据覆盖。若覆盖操作与文件系统镜像分裂同时发生,导致持久文件数据丢失的可能性非常小,因此无需特殊处理。向持久文件写入后,不会强制同步到存储介质(不会调用 fsync())。

只有在成功将匹配的日志文件记录或元数据(已处理的日志大小和修改时间)报告给 Zabbix 服务器后,才会使用最新数据进行覆盖。如果日志文件持续变化,这种情况可能会在每次监控项检查时发生。

agent 关闭时不执行任何特殊操作。

在收到活动检查列表后,agent 会将过时的持久化文件标记为删除。

如果满足以下条件之一,持久化文件就会变为过时:

  1. 对应的日志监控项不再被监控。
  2. 某个日志监控项被重新配置为与之前不同的 persistent_dir 位置。

删除会延迟 24 小时执行,因为处于 NOTSUPPORTED 状态的日志文件不会包含在活动检查列表中,但它们之后可能会变为 SUPPORTED,而其持久化文件届时会有用。

如果 agent 在 24 小时到期前停止,那么这些过时文件将不会被删除,因为 Zabbix agent 不再从 Zabbix 服务器获取它们位置的信息。

在 agent 停止期间,如果将某个日志监控项的 persistent_dir 重新配置回旧的 persistent_dir 位置,而用户没有删除旧的持久化文件,则会导致 agent 从旧的持久化文件恢复状态,从而造成消息遗漏或误报。

持久化文件的命名和位置

Zabbix agent 根据其键值区分主动检查。 例如,logrt[/home/zabbix/test.log] 和 logrt[/home/zabbix/test.log,] 是不同的监控项。 在前端中将监控项 logrt[/home/zabbix/test.log,,,10] 修改为 logrt[/home/zabbix/test.log,,,20],会导致从 agent 的主动检查列表中删除监控项 logrt[/home/zabbix/test.log,,,10],并创建 logrt[/home/zabbix/test.log,,,20] 监控项 (某些属性会在前端/服务器中的修改过程中被沿用,但不会在 agent 中沿用)。

文件名由监控项键值的 MD5 校验和组成,并附加监控项键值长度,以降低冲突的可能性。 例如,logrt[/home/zabbix50/test.log,,,,,,,,/home/zabbix50/agent_private] 监控项的状态将保存在持久化文件 c963ade4008054813bbc0a650bb8e09266 中。

多个日志监控项可以使用相同的 persistent_dir 值。

persistent_dir 的指定需要考虑特定的文件系统布局、挂载点和挂载选项以及存储镜像配置 - 持久化文件应位于与被监控日志文件相同的镜像文件系统上。

如果无法创建 persistent_dir 目录,或该目录不存在,或者 Zabbix agent 的访问权限不允许创建/写入/读取/删除文件,则该日志监控项将变为 NOTSUPPORTED。

如果在 agent 运行期间移除了对持久存储文件的访问权限,或者发生其他错误(例如磁盘已满),则错误会记录到 agent 日志文件中,但日志监控项不会变为 NOTSUPPORTED。

I/O 负载

监控项的持久化文件会在每次成功将一批数据(包含监控项的数据)发送到服务器后更新。 例如,默认 BufferSize 为 100。 如果某个日志监控项找到了 70 条匹配记录,那么前 50 条记录将作为一个批次发送,持久化文件会更新,然后剩余的 20 条记录将作为第二个批次发送(在积累更多数据时,可能会有一些延迟),并且持久化文件会再次更新。

agent 与 server 之间通信失败时的操作

log[]logrt[] 监控项的每一条匹配行,以及每个 log.count[]logrt.count[] 监控项检查的结果,都需要在 agent 发送缓冲区指定的 50% 区域中占用一个空闲槽位。
缓冲区中的元素会定期发送到 server(或 proxy),随后缓冲区槽位再次变为空闲。

只要 agent 发送缓冲区中指定日志区域还有空闲槽位,并且 agent 与 server(或 proxy)之间的通信失败,日志监控结果就会累积在发送缓冲区中。
这有助于缓解短暂的通信故障。

在较长时间的通信故障期间,所有日志槽位都会被占满,并采取以下操作:

  • log[]logrt[] 监控项检查会停止。
    当通信恢复且缓冲区中有可用空闲槽位时,检查会从上一次的位置继续。
    不会丢失任何匹配行,只是会稍后报告。
  • 如果 maxdelay = 0(默认值),log.count[]logrt.count[] 检查会停止。
    其行为与上文所述的 log[]logrt[] 监控项类似。
    请注意,这可能会影响 log.count[]logrt.count[] 的结果:例如,一次检查在日志文件中统计到 100 条匹配行,但由于缓冲区中没有空闲槽位,检查被停止。
    当通信恢复后,agent 会再次统计这 100 条匹配行以及另外 70 条新的匹配行。
    此时 agent 发送的 count = 170,就像这些结果是在一次检查中得到的一样。
  • 对于 maxdelay > 0log.count[]logrt.count[] 检查:如果检查过程中没有发生“跳跃”,则行为与上文所述类似。
    如果发生了跨越日志文件行的“跳跃”,则会保留“跳跃”后的位置信息,并丢弃已统计的结果。
    因此,即使在通信失败的情况下,agent 也会尽量跟上不断增长的日志文件。

正则表达式编译和运行时错误的处理

如果在 log[]logrt[]log.count[]logrt.count[] 监控项中使用的正则表达式无法被 PCRE 或 PCRE2 库编译,则该监控项将进入 NOTSUPPORTED 状态,并显示错误消息。
要继续监控该日志监控项,应修正该正则表达式。

如果正则表达式可以成功编译,但在运行时失败(在某些或全部日志记录上失败),则该日志监控项仍保持受支持状态,监控继续进行。
运行时错误会记录到 Zabbix agent 的日志文件中(不包含日志文件记录内容)。

为允许 Zabbix agent 监控自身的日志文件,日志记录速率限制为每次检查最多记录一个运行时错误。
例如,如果分析了 10 条记录,其中 3 条因 regexp 运行时错误而失败,则 agent 日志中只会生成 1 条记录。

例外情况:如果 MaxLinesPerSecond=1 且更新间隔为 1(即每次检查只允许分析 1 条记录),则不会记录 regexp 运行时错误。

在发生运行时错误时,zabbix_agentd 会记录监控项键值,而 zabbix_agent2 会记录监控项 ID,以帮助识别哪些日志监控项存在运行时错误。
建议在发生运行时错误时重新设计正则表达式。