6 日志文件监控
概述
Zabbix 可用于集中监控和分析日志文件,并支持/不支持日志轮转。
当日志文件包含某些字符串或字符串模式时,可使用通知来警告用户。
要监控日志文件,必须具备:
- 在主机上运行的 Zabbix agent
- 已设置好的日志监控项
受监控日志文件的大小限制取决于大文件支持。
配置
验证 agent 参数
请确保在 agent 配置文件 中:
Hostname参数与前端中的主机名称一致。ServerActive参数中指定了用于处理主动检查的服务器。
监控项配置
配置一个日志监控监控项。

所有必填输入字段都以红色星号标记。
对于日志监控监控项,需要特别填写:
| Type | 在此选择 Zabbix agent (active)。 |
| Key | 使用以下监控项键之一: log[] 或 logrt[]: 这两个监控项键可用于监控日志,并在提供内容正则表达式时按其过滤日志条目。 例如: log[/var/log/syslog,error]。请确保文件对 'zabbix' 用户具有读取权限,否则监控项状态将被设置为 'unsupported'。log.count[] 或 logrt.count[]: 这两个监控项键仅返回匹配行的数量。 有关这些监控项键及其参数用法的详细信息,请参见受支持的 Zabbix agent 监控项 键部分。 |
| Type of information | 自动预填: 对于 log[] 或 logrt[] 监控项 - Log;对于 log.count[] 或 logrt.count[] 监控项 - Numeric (unsigned)。如果可选地使用 output 参数,则可以手动选择除 Log 之外的适当信息类型。请注意,选择非 Log 类型的信息将导致本地时间戳丢失。 |
| Update interval (in sec) | 该参数定义 Zabbix agent 检查日志文件中是否有任何更改的频率。将其设置为 1 秒可确保您尽快获取新记录。 |
| Log time format | 在此字段中,您可以选择性地指定用于解析日志行时间戳的模式。支持的占位符: * y:年 (1970-2038) * M:月 (01-12) * d:日 (01-31) * h:小时 (00-23) * m:分钟 (00-59) * s:秒 (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 服务器,并且在 Zabbix agent 停止时会丢失。
- 不要修改日志文件的最后修改时间(例如使用
touch),也不要通过将文件复制回其原始名称来替换被监控的日志文件(这会创建新的 inode)。 在这两种情况下,Zabbix 都可能将该文件视为不同的文件并从头重新读取,从而产生重复告警。 - 如果
logrt[]监控项有多个匹配的日志文件,并且 Zabbix agent 正在跟踪其中最新的一个,而这个最新日志文件被删除,则会记录一条警告消息"there are no files matching "<regexp mask>" in "<directory>"。 对于正在检查的logrt[]监控项,Zabbix agent 会忽略最后修改时间早于 agent 已见过的最新修改时间的日志文件。
- agent 会从上次停止的位置开始继续读取日志文件。
- 已分析的字节数(大小计数器)和最后修改时间(时间计数器)存储在 Zabbix 数据库中,并发送给 agent,以确保在 agent 刚启动,或收到之前被禁用或不受支持的监控项时,agent 能从该位置开始读取日志文件。 但是,如果 agent 从服务器收到了非零的大小计数器,而 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 服务器的匹配记录不会超过 20 条。 通过增大 agent 配置文件中的 MaxLinesPerSecond,或在监控项键中设置 maxlines 参数,可将单次检查的上限提高到最多分析 10000 条日志记录,并向 Zabbix 服务器发送 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 会将这些符号替换为 "?",以便继续处理该行直到换行符。
提取正则表达式的匹配部分
有时,当找到正则表达式匹配时,我们可能希望只从目标文件中提取感兴趣的值,而不是返回整行内容。
日志监控项能够从匹配的行中提取所需的值。
这是通过 log 和 logrt 监控项中的附加 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 服务器不可用,这类应用程序会持续向日志文件中刷入成千上万条几乎相同的错误消息,直到恢复正常运行。
默认情况下,所有这些消息都会被逐一分析,并按照 log 和 logrt 监控项中的配置,将匹配的行发送到服务器。
内置的过载保护包括一个可配置的 maxlines 参数(防止服务器接收过多匹配的日志行)以及一个 10*maxlines 的限制(防止 agent 在一次检查中使主机 CPU 和 I/O 过载)。
不过,内置保护仍然存在 2 个问题。
首先,大量可能信息价值不高的消息会被上报到服务器,并占用数据库空间。
其次,由于每秒可分析的行数有限,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 重启后,日志监控项的状态会从持久化文件中恢复。
其主要使用场景是监控位于镜像文件系统上的日志文件。
在某个时刻之前,日志文件会同时写入两个镜像。
随后镜像被拆分。
在活动副本上,日志文件仍会继续增长并接收新记录。
Zabbix agent 会对其进行分析,并将已处理的日志大小和修改时间发送给服务器。
在被动副本上,日志文件保持不变,明显落后于活动副本。
之后,操作系统和 Zabbix agent 会从被动副本重新启动。
此时,Zabbix agent 从服务器接收到的已处理日志大小和修改时间,可能不适用于被动副本上的实际情况。
为了从文件系统镜像拆分时 agent 停止的位置继续监控日志文件,agent 会从持久化文件中恢复其状态。
使用持久文件的 agent 操作
启动时,Zabbix agent 对持久文件一无所知。 只有在从 Zabbix 服务器(proxy)接收到活动检查列表后,agent 才会发现某些日志监控项应由指定目录下的持久文件提供支持。
在 agent 运行期间,会打开持久文件以进行写入(使用 fopen(filename, "w")),并用最新数据覆盖其内容。 如果覆盖写入与文件系统镜像分裂同时发生,则丢失持久文件数据的可能性非常小,因此对此不做特殊处理。 写入持久文件后,不会强制同步到存储介质(即不会调用 fsync())。
在将匹配的日志文件记录或元数据(已处理的日志大小和修改时间)成功上报给 Zabbix 服务器后,会用最新数据进行覆盖。 如果日志文件持续变化,这种情况可能会频繁到每次监控项检查后都发生。
在 agent 关闭期间,不执行任何特殊操作。
在收到活动检查列表后,agent 会将已过时的持久文件标记为待删除。
持久文件在以下情况下会变为过时:
- 对应的日志监控项不再被监控。
- 日志监控项被重新配置,且 persistent_dir 位置与之前不同。
删除操作会延迟 24 小时执行,因为处于 NOTSUPPORTED 状态的日志文件不会包含在活动检查列表中,但它们之后可能会变为 SUPPORTED,此时其持久文件仍然有用。
如果在 24 小时到期前停止 agent,则这些过时文件不会被删除,因为 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 条记录将在第 2 批中发送(当积累了更多数据时,可能会有一些延迟),持久文件将再次更新。
agent 与服务器之间通信失败时的操作
log[] 和 logrt[] 监控项的每一条匹配行,以及每次 log.count[] 和 logrt.count[] 监控项检查的结果,都需要在 agent 发送缓冲区中预留的 50% 区域内占用一个空闲槽位。
缓冲区元素会定期发送到服务器(或 proxy),随后这些缓冲区槽位会再次变为空闲。
当 agent 发送缓冲区中为日志预留的区域仍有空闲槽位,而 agent 与服务器(或 proxy)之间通信失败时,日志监控结果会累积在发送缓冲区中。
这有助于缓解短暂的通信故障。
在较长时间的通信故障期间,所有日志槽位都会被占满,并采取以下操作:
log[]和logrt[]监控项检查会停止。
当通信恢复且缓冲区中有可用空闲槽位时,检查将从之前的位置继续。
不会丢失任何匹配行,只是会延后上报。- 如果
maxdelay = 0(默认值),log.count[]和logrt.count[]检查会停止。
其行为与上文所述的log[]和logrt[]监控项类似。
请注意,这可能会影响log.count[]和logrt.count[]的结果:例如,某次检查在日志文件中统计到 100 条匹配行,但由于缓冲区中没有空闲槽位,检查被停止。
当通信恢复后,agent 会统计同样的这 100 条匹配行,以及另外新增的 70 条匹配行。
此时 agent 会发送 count = 170,就好像这些匹配行是在一次检查中发现的一样。 - 对于
maxdelay > 0的log.count[]和logrt.count[]检查:如果检查期间没有发生“跳跃”,则行为与上文描述类似。
如果发生了跨越日志文件行的“跳跃”,则会保留“跳跃”之后的位置,而已统计的结果会被丢弃。
因此,即使在通信失败的情况下,agent 也会尽量跟上不断增长的日志文件。
正则表达式编译和运行时错误的处理
如果 log[]、logrt[]、log.count[] 或 logrt.count[] 监控项中使用的正则表达式无法被 PCRE 或 PCRE2 库编译,则该监控项会进入
NOTSUPPORTED 状态,并显示一条错误消息。
要继续监控该日志监控项,应修正该正则表达式。
如果正则表达式能够成功编译,但在运行时失败(在某些或全部日志记录上),则该日志监控项仍保持受支持状态, 监控会继续进行。 运行时错误会记录在 Zabbix agent 日志文件中(不包含日志文件记录本身)。
日志记录速率限制为每次检查最多一条运行时错误,以便 Zabbix agent 能够监控其自身的日志文件。 例如,如果分析了 10 条记录,其中 3 条记录因正则表达式运行时错误而失败,则 agent 日志中只会生成一条记录。
例外情况:如果 MaxLinesPerSecond=1 且 update interval=1(每次检查只允许分析 1 条记录),则不会记录正则表达式运行时错误。
发生运行时错误时,zabbix_agentd 会记录监控项键值,zabbix_agent2 会记录监控项 ID,以帮助识别哪个日志监控项存在运行时错误。 如果出现运行时错误,建议重新设计该正则表达式。