这是原厂英文文档的翻译页面. 欢迎帮助我们 完善文档.
2022 Zabbix中国峰会
2022 Zabbix中国峰会

2 触发器表达式

概览

triggers(触发器) 中使用的表达式非常灵活。 您可以使用它们来创建复杂的逻辑测试 监控统计。

一个简单的表达式使用 function(函数) 应用于监控项的 一些参数。该函数返回一个与阈值比较后的结果,使用运算符和常数。

一个简单有用的表达式的语法是 function(/host/key,parameter)<operator><constant>.

例如:

  min(/Zabbix server/net.if.in[eth0,bytes],5m)>100K

如果在最后五分钟期间接收到的网络字节数最小值超过 100 KB 将触发。

虽然语法完全相同,但从功能的角度来看 有两种类型的触发器表达式:

  • 问题表达 - 定义问题的条件
  • 恢复表达式(可选) - 定义附加条件 问题解决

当单独定义问题表达式时,该表达式将同时用作问题阈值和问题恢复阈值。只要问题表达式的计算结果为TRUE,就会出现问题。只要问题表达式的计算结果为FALSE,问题就解决了。

当定义问题表达式和补充恢复表达式时,问题解决将变得更加复杂:不仅问题表达式必须为FALSE,而且恢复表达式也必须为TRUE。这对于创建hysteresis滞后和避免触发器振荡非常有用。

函数

函数允许计算收集的值(average 平均值、minimum 最小值、maximum 最大值、sum 总和)、查找字符串、参考当前时间和其他因素。

支持的函数可用的完整列表。

通常,函数会返回数值以进行比较。返回字符串时,可以使用 =<> 运算符进行比较(参见示例)。

函数参数

函数参数允许选项:

  • 主机和监控项(仅引用主机项目历史的功能)
  • 功能特定的参数
  • 其他表达式(不适用于引用主机的函数 监控项,历史数据,请参阅 other expressions(其他表达式) 例子)

主机和监控项键可以指定为/host/key。被引用的监控项必须处于支持的状态(nodata()无数据 函数除外, 这也是为不受支持的监控项计算的)。

而作为函数参数的其他触发器表达式仅限于 触发器中的非历史函数,此限制不适用于 calculated items(计算监控项)

特定函数参数

特定函数的参数放置在监控项之后,并且是用逗号与监控项键隔开。请参阅 supported functions(支持的函数) 获取这些的完整列表参数。

Preceded by a hashtag, the parameter has a different meaning: 大多数数值函数都接受时间作为参数。您可以使用 seconds 或 time suffixes(时间后缀) 来表示时间。 前置#号的参数有不同的含义:

表达式 描述
sum(/host/key,10m) 最近 10 分钟的数值总和.
sum(/host/key,#10) 最后十个值的总和.

前置#号的参数用于last函数含义不同 - 它们表示第 N 个先前的值,因此给定值 3、7、 2、6、5(从最近到最近): (从最近到最远):

  • last(/host/key,#2) 返回 '7'
  • last(/host/key,#5) 返回 '5'
时间偏移

支持可选的时间偏移,时间或值计数作为函数参数。此参数允许从一个引用过去一段时间的数据。

时移以 now 开头 - 指定当前时间,并且是 后跟 +N<time unit>-N<time unit> - 加或减 N 时间单位

例如,avg(/host/key,1h:now-1d) 将返回一天前的一个小时的平均值。

具有绝对时间段的时移

时移参数支持绝对时间段,例如午夜,一天到午夜,一周的周一到周日,第一天到最后一天,一个月到下一个月。

绝对时间段的时移以 now 开始 - 指定当前时间,然后是任意数量的时间操作:/<time unit> - 定义时间单位的开始和结束,例如,从午夜到一天的午夜,+N<time unit>-N<time unit> - 添加或减去 N 个时间单位.

请注意时移的值可以大于或等于0, 而时间段最小值为1。

参数 描述
1d:now/d 昨天
1d:now/d+1d 今天
2d:now/d+1d 过去 2 天
1w:now/w 上星期
1w:now/w+1w 这星期
其他表达式

函数参数可能包含其他表达式,如下所示 语法:

min(min(/host/key,1h),min(/host2/key2,1h)*10)

请注意,如果函数引用,则可能不会使用其他表达式 监控项历史。例如,不允许使用以下语法:

min(/host/key,#5*10)

运算符

触发器支持下列运算符 (在执行中优先级递减)

优先级 运算符 定义 注意 unknown values(未知值) 强制转换操作为浮点数 1
1 - 负数 -Unknown → Unknown Yes
2 not 逻辑非 not Unknown → Unknown Yes
3 * 乘法 0 * Unknown → Unknown
(yes, Unknown, not 0 - to not lose
算术运算中的未知数)
1.2 * Unknown → Unknown
Yes
/ 除法 Unknown / 0 → error
Unknown / 1.2 → Unknown
0.0 / Unknown → Unknown
Yes
4 + 算术加 1.2 + Unknown → Unknown Yes
- 算术减 1.2 - Unknown → Unknown Yes
5 < 少于. 运算符定义为:

A<B ⇔ (A<B-0.000001)
1.2 < Unknown → Unknown Yes
<= 小于或等于。运算符定义为:

A<=B ⇔ (A≤B+0.000001)
Unknown <= Unknown → Unknown Yes
> 多于。运算符定义为:

A>B ⇔ (A>B+0.000001)
Yes
>= More than or equal to. The operator is defined as:

A>=B ⇔ (A≥B-0.000001)
Yes
6 = 等于。运算符定义为:

A=B ⇔ (A≥B-0.000001) and (A≤B+0.000001)
No 1
<> 不等于。运算符定义为:

A<>B ⇔ (A<B-0.000001) or (A>B+0.000001)
No 1
7 and 逻辑与 0 and Unknown → 0
1 and Unknown → Unknown
Unknown and Unknown → Unknown
Yes
8 or 逻辑或 1 or Unknown → 1
0 or Unknown → Unknown
Unknown or Unknown → Unknown
Yes

1 如果字符串操作数仍然转换为数字:

  • 另一个操作数是数字
  • 运算符以外的 = or <> 在操作数上使用

(如果转换失败 - 数字操作数被转换为字符串操作数并且 两个操作数都作为字符串进行比较。

notandor 运算符区分大小写,并且必须在 小写。它们还必须用空格或括号括起来。

-not 外,所有运算符都从左到右 关联性。 -not 是非关联的(意思是 -(-1)not (not 1) 应该用来代替 --1不是不是 1)。

评价结果:

  • <, <=, >, >=, =, <> 如果指定的运算符应在触发器表达式中产生“1” 关系为真,如果为假,则为“0”。如果至少有一个操作数是 未知结果为未知;
  • and 对于已知操作数,如果它的两个操作数都将产生“1” 则不等于'0';否则,它产生“0”;对于未知 仅当一个操作数比较等于时,操作数and才会产生“0” '0';否则,它会产生“未知”.
  • or 对于已知的操作数,如果它的任何一个操作数都将产生“1” 则不等于'0';否则,它产生“0”;对于未知 仅当一个操作数比较不等于0时,操作数or才会产生“1”;否则,它会产生“未知”;
  • 逻辑否定运算符 not 的结果 如果其操作数的值比较不等于“0”,则操作数为“0”; 如果其操作数的值比较等于“0”,则为“1”。对于未知 操作数 not 产生“未知”。

缓存值

触发器评估所需的值由Zabbix server缓存。由于此触发器评估在服务器重新启动后一段时间导致较高的数据库负载。当监控项历史数据被移除(手动或housekeeper)时,缓存值不会被清除,因此服务器将使用缓存的值,直到它们比触发器函数中定义的时间段或服务器重启的时间长。

触发器示例

示例 1

Zabbix server上的处理器负载太高。

last(/Zabbix server/system.cpu.load[all,avg1])>5

'/Zabbix server/system.cpu.load[all,avg1]' 给出了被监控参数的简短名称。它指定了服务器是“Zabbix server”,监控项的键值是“system.cpu.load[all,avg1]”。通过使用函数“last()”获取最新的值。最后,“>5”意味着当Zabbix server最新获取的处理器负载值大于5时触发器就会处于异常状态。

示例 2

www.example.com 已超载。

last(/www.example.com/system.cpu.load[all,avg1])>5 or min(/www.example.com/system.cpu.load[all,avg1],10m)>2 

当前处理器负载超过5或过去10分钟内CPU负载都超过2。

示例 3

/etc/passwd文件被修改

(last(/www.example.com/vfs.file.cksum[/etc/passwd],#1)<>last(/www.example.com/vfs.file.cksum[/etc/passwd],#2))=1

当 /etc/passwd 校验和的前一个值与最近的值不同时,表达式为真。

类似的表达式可能有助于监控重要的文件变化 ,例如 /etc/passwd、/etc/inetd.conf、/kernel 等。

示例 4

服务器网卡从 Internet 下载一个大文件。 min 函数的使用:

min(/www.example.com/net.if.in[eth0,bytes],5m)>100K

在过去5分钟内,eth0上接收字节数大于100kb时,表达式为true。

示例 5

SMTP服务群集的两个节点都停止。 注意在一个表达式中使用两个不同的主机:

last(/smtp1.example.com/net.tcp.service[smtp])=0 and last(/smtp2.example.com/net.tcp.service[smtp])=0

当两个SMTP服务器(smtp1.example.com 和 smtp2.example.com)的smtp服务关闭时为真。

示例 6

Zabbix 代理需要升级。 函数 find() 的使用:

find(/example.example.com/agent.version,,"like","beta8")=1

如果 Zabbix 代理的版本为 beta8,则表达式为真。

示例 7

服务器无法访问。

count(/example.example.com/icmpping,30m,,"0")>5

如果主机“example.example.com” 在过去 30 分钟内超过 5 次无法访问,则表达式为真。

示例 8

最近 3 分钟内没有心跳。 函数 nodata() 的使用:

nodata(/example.example.com/tick,3m)=1

要使用这个触发器,'tick'必须定义成一个trapper陷阱器监控项。主机应该使用zabbix_sender定期发送这个监控项的数据。如果在180秒内没有接收到数据,则触发值变为异常状态。

注释 ‘nodata’可以在任何类型的监控项中使用。

示例 9

夜间的CPU负载

使用time()函数:

min(/Zabbix server/system.cpu.load[all,avg1],5m)>2 and time()>000000 and time()<060000

触发器只能在晚上 (00:00-06:00) 将其状态更改为 true。

示例 10

CPU 活动随时异常。

使用函数 time() 和 not 运算符:

· min(/zabbix/system.cpu.load[all,avg1],5m)>2 · and not (dayofweek()=7 and time()>230000) · and not (dayofweek()=1 and time()<010000)

触发器可以随时将其状态更改为真,每周更改 2 小时(星期日,23:00 - 星期一,01:00)除外。

示例 10

检查客户端本地时间是否与 Zabbix 服务器时间同步。 使用fuzzytime()函数:

fuzzytime(/MySQL_DB/system.localtime,10s)=0

当MySQL_DB服务器的本地时间与Zabbix server之间的时间相差超过10秒,触发器将变为异常状态。 注意 'system.localtime' 必须配置为 passive check被动检查.

示例 11

比较今天的平均负载和昨天同一时间的平均负载(使用时移作为now-1d)。

avg(/server/system.cpu.load,1h)/avg(/server/system.cpu.load,1h:now-1d)>2

如果最后一小时的平均负载超过昨天同一小时的平均负载两倍,触发器将触发。

示例 12

使用了另一个监控项的值来获得触发器的阈值:

last(/Template PfSense/hrStorageFree[{#SNMPVALUE}])<last(/Template PfSense/hrStorageSize[{#SNMPVALUE}])*0.1

如果可用存储量低于 10%,触发器将触发。

示例 13

使用evaluation result评估结果获取超过阈值的触发器数量:

(last(/server1/system.cpu.load[all,avg1])>5) + (last(/server2/system.cpu.load[all,avg1])>5) + (last(/server3/system.cpu.load[all,avg1])>5)>=2

如果表达式中至少有两个触发器大于5,触发器将触发。

示例 14

比较两个监控项的字符串值 - 这里的操作数是返回字符串的函数 。

问题:如果两台主机Ubuntu版本不同,则产生告警。

last(/NY Zabbix server/vfs.file.contents[/etc/os-release])<>last(/LA Zabbix server/vfs.file.contents[/etc/os-release])
示例 15

比较两个字符串值 - 操作数是:

  • 返回字符串的函数
  • 宏和字符串的组合

问题:检测 DNS 查询的变化

监控项键是:

net.dns.record[8.8.8.8,{$WEBSITE_NAME},{$DNS_RESOURCE_RECORD_TYPE},2,1]

宏定义为

{$WEBSITE_NAME} = example.com
       {$DNS_RESOURCE_RECORD_TYPE} = MX

并且通常返回:

example.com           MX       0 mail.example.com

检测DNS查询结果是否与预期的结果有偏差的触发器表达式如下:

last(/Zabbix server/net.dns.record[8.8.8.8,{$WEBSITE_NAME},{$DNS_RESOURCE_RECORD_TYPE},2,1])<>"{$WEBSITE_NAME}           {$DNS_RESOURCE_RECORD_TYPE}       0 mail.{$WEBSITE_NAME}"

注意第二个操作数的引号。

示例 16

比较两个字符串值 - 操作数是:

  • 返回字符串的函数
  • 带有特殊字符 \ 和 " 的字符串常量

问题:检测/tmp/hello文件内容是否等于:

\" //hello ?\"

选项1)直接写字符串

last(/Zabbix server/vfs.file.contents[/tmp/hello])="\\\" //hello ?\\\""

请注意在比较字符串时如何转义 \ 和 " 字符。

选项 2) 使用宏

{$HELLO_MACRO} = \" //hello ?\"

在表达式中:

last(/Zabbix server/vfs.file.contents[/tmp/hello])={$HELLO_MACRO}
示例 17

比较长期周期。

问题:上个月 Exchange 服务器的负载增加了 10% 以上

trendavg(/Exchange/system.cpu.load,1M:now/M)>1.1*trendavg(/Exchange/system.cpu.load,1M:now/M-1M)

您也可以在触发器配置中使用 Event name(事件名称),构建有意义的警报消息,例如如下内容。

"Load of Exchange server increased by 24% in July (0.69) comparing to June (0.56)"

事件名称必须定义为:

Load of {HOST.HOST} server increased by {{?100*trendavg(//system.cpu.load,1M:now/M)/trendavg(//system.cpu.load,1M:now/M-1M)}.fmtnum(0)}% in {{TIME}.fmttime(%B,-1M)} ({{?trendavg(//system.cpu.load,1M:now/M)}.fmtnum(2)}) comparing to {{TIME}.fmttime(%B,-2M)} ({{?trendavg(//system.cpu.load,1M:now/M-1M)}.fmtnum(2)})

这种情况在触发器配置中允许手动关闭也很有用 。

Have a trigger expressions example that might be useful to others? Use the Example suggestion form to send it to Zabbix developers.

滞后

有时,问题和恢复状态之间需要一个间隔,而不是一个简单的阈值。例如,如果我们想定义一个触发器,它在服务器机房温度高于20°C时报告问题,并且我们想让它在温度低于15°C之前保持问题状态,那么简单的触发器阈值为20°C是不够的。

相反,我们需要首先为问题事件定义一个触发器表达式(温度高于20°C)。然后我们需要定义一个额外的恢复条件(温度低于15°C)。这是通过在defining定义触发器时定义一个额外的Recovery expression 恢复表达式参数来实现的。

在这种情况下,问题恢复将分两步进行:

  • 首先,问题表达式(温度高于 20°C)评估为 FALSE
  • 其次,恢复表达式(温度低于 15°C)评估为 TRUE

仅当问题事件为 先解决。

当问题表达式为TRUE时,即使恢复表达式为TRUE也不会恢复。

示例 1

机房温度过高。

问题表达式:

last(/server/temp)>20

恢复表达式:

last(/server/temp)<=15
示例 2

磁盘剩余空间过低。

问题表达式: 最后 5 分钟小于 10GB

max(/server/vfs.fs.size[/,free],5m)<10G

恢复表达式:最近10分钟超过40GB

min(/server/vfs.fs.size[/,free],10m)>40G

不支持项的表达式和未知的值

Zabbix3.2之前的版本对触发器表达式中不支持的监控项非常严格。表达式中的任何不支持的监控项都会立即将触发器值呈现为“未知”。

从Zabbix3.2开始通过将未知值引入到表达式评估中,对不受支持的项有更灵活的方法:

  • 对于nodata()函数,监控项是否支持不影响。即使引用不支持的监控项,函数也会评估。
  • 具有 OR 和 AND 的逻辑表达式可以计算为已知值 无论未知操作数如何,在两种情况下:
    • "1 or 不支持的监控项函数1 or 不支持的监控项函数2 or ..." 可以被评估为'1' (True),
    • "0 and 不支持的监控项函数1 and 不支持的监控项函数2 and ..." 可以被评估为'0' (False),
      Zabbix试图评估不支持的监控项作为Unknown值的逻辑表达式。在上述两种情况下,将产生一个已知值;在其他情况下,触发值将是Unknown
  • 如果对受支持监控项的函数评估导致错误,则 函数值为Unknown,参与进一步表达 评估。

请注意,未知值可能仅在逻辑表达式中“消失”为 如上所述。在算术表达式中,未知值总是导致 结果“未知”(除以 0 除外)

如果具有多个不受支持的监控项的触发器表达式计算为 Unknown ,前端的错误信息指向最后一个评估不支持的监控项。