[comment]: # translation:outdated

[comment]: # ({259e4adb-e12f7cb4})
# 8 自定义 LLD 规则

[comment]: # ({/259e4adb-e12f7cb4})

[comment]: # ({5678f7e6-c6cb7a14})
### 概述

也可以创建完全自定义的 LLD 规则，用于发现任何类型的实体——例如，数据库服务器上的数据库。

为此，应创建一个自定义监控项，使其返回一个 JSON 字符串，用于指定已发现的对象，以及可选的它们的一些属性。  
每个实体的宏数量没有限制——内置发现规则通常返回一个或两个宏（例如，文件系统发现会返回两个宏），而自定义规则可以返回更多。

[comment]: # ({/5678f7e6-c6cb7a14})

[comment]: # ({9ba1159d-124235ad})
### 示例

所需的 JSON 字符串格式最好通过示例来说明。
假设您正在运行一个旧版 Zabbix 1.8 agent（即不支持 [`vfs.fs.discovery`](/manual/config/items/itemtypes/zabbix_agent#vfs.fs.discovery) 键的版本），但您仍然需要发现文件系统。
下面是一个适用于 Linux 的简单 Perl 脚本，用于发现已挂载的文件系统并以 JSON 格式输出，其中包含文件系统名称和类型。
其一种使用方式是将其作为一个 UserParameter，键为 `vfs.fs.discovery_perl`：

```perl
#!/usr/bin/perl

$first = 1;

print "[\n";

for (`cat /proc/mounts`)
{
    ($fsname, $fstype) = m/\S+ (\S+) (\S+)/;

    print "\t,\n" if not $first;
    $first = 0;

    print "\t{\n";
    print "\t\t\"{#FSNAME}\":\"$fsname\",\n";
    print "\t\t\"{#FSTYPE}\":\"$fstype\"\n";
    print "\t}\n";
}

print "]\n";
```

::: noteimportant
LLD 宏名称允许使用的符号为 **0-9**、**A-Z**、**\_**、**.**。
名称中不支持小写字母。
:::

其输出示例如下所示（为便于阅读，已重新格式化）。
自定义发现检查的 JSON 必须遵循相同的格式。

```javascript
[
    { "{#FSNAME}":"/",                           "{#FSTYPE}":"rootfs"   },
    { "{#FSNAME}":"/sys",                        "{#FSTYPE}":"sysfs"    },
    { "{#FSNAME}":"/proc",                       "{#FSTYPE}":"proc"     },
    { "{#FSNAME}":"/dev",                        "{#FSTYPE}":"devtmpfs" },
    { "{#FSNAME}":"/dev/pts",                    "{#FSTYPE}":"devpts"   },
    { "{#FSNAME}":"/lib/init/rw",                "{#FSTYPE}":"tmpfs"    },
    { "{#FSNAME}":"/dev/shm",                    "{#FSTYPE}":"tmpfs"    },
    { "{#FSNAME}":"/home",                       "{#FSTYPE}":"ext3"     },
    { "{#FSNAME}":"/tmp",                        "{#FSTYPE}":"ext3"     },
    { "{#FSNAME}":"/usr",                        "{#FSTYPE}":"ext3"     },
    { "{#FSNAME}":"/var",                        "{#FSTYPE}":"ext3"     },
    { "{#FSNAME}":"/sys/fs/fuse/connections",    "{#FSTYPE}":"fusectl"  }
]
```

在前一个示例中，要求键名与原型中使用的 LLD 宏名称匹配；另一种方式是使用 JSONPath 提取 LLD 宏值，即 `{#FSNAME}` → `$.fsname` 和 `{#FSTYPE}` → `$.fstype`，从而可以使用如下脚本：

```perl
#!/usr/bin/perl
 
$first = 1;
 
print "[\n";
 
for (`cat /proc/mounts`)
{
    ($fsname, $fstype) = m/\S+ (\S+) (\S+)/;
 
    print "\t,\n" if not $first;
    $first = 0;
 
    print "\t{\n";
    print "\t\t\"fsname\":\"$fsname\",\n";
    print "\t\t\"fstype\":\"$fstype\"\n";
    print "\t}\n";
}
 
print "]\n";
```

其输出示例如下所示（为便于阅读，已重新格式化）。

```javascript
[
    { "fsname":"/",                           "fstype":"rootfs"   },
    { "fsname":"/sys",                        "fstype":"sysfs"    },
    { "fsname":"/proc",                       "fstype":"proc"     },
    { "fsname":"/dev",                        "fstype":"devtmpfs" },
    { "fsname":"/dev/pts",                    "fstype":"devpts"   },
    { "fsname":"/lib/init/rw",                "fstype":"tmpfs"    },
    { "fsname":"/dev/shm",                    "fstype":"tmpfs"    },
    { "fsname":"/home",                       "fstype":"ext3"     },
    { "fsname":"/tmp",                        "fstype":"ext3"     },
    { "fsname":"/usr",                        "fstype":"ext3"     },
    { "fsname":"/var",                        "fstype":"ext3"     },
    { "fsname":"/sys/fs/fuse/connections",    "fstype":"fusectl"  }
]
```

然后，在发现规则的 *Filter* 字段中，您可以将 `{#FSTYPE}` 指定为宏，并将 `rootfs|ext3` 指定为正则表达式。

::: noteclassic
使用自定义 LLD 规则时，您不必使用像 `FSNAME`/`FSTYPE` 这样的宏名称，您可以自由使用任何您喜欢的名称。
如果使用 JSONPath，则 LLD 行将是一个数组元素，它可以是一个对象，也可以是另一个数组或一个值。
:::

请注意，如果使用用户参数，则返回值限制为 16 MB。
更多详细信息，请参见 [LLD 返回值的数据限制](/manual/discovery/low_level_discovery/notes#data-limits-for-return-values)。

[comment]: # ({/9ba1159d-124235ad})
