[comment]: # ({5fe07def-23e7eeb7})


# 6 条自定义 LLD 规则

[comment]: # ({/5fe07def-23e7eeb7})

[comment]: # ({dee5ac37-a6970558})


### 概述

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

为此，需要创建一个自定义监控项，该脚本应返回一个JSON string，其中指定发现的objects及其可选属性。每个实体可定义的宏数量没有限制——虽然内置发现规则通常返回一个或两个宏（例如文件系统发现会返回两个宏），但实际可以返回更多宏。

[comment]: # ({/dee5ac37-a6970558})

[comment]: # ({ddf73092-5a4f43c4})


### 示例

所需的JSON string格式通过示例最能说明。假设我们
正在运行一个旧的Zabbix 1.8 agent（不支持
"vfs.fs.discovery"的版本），但我们仍需要发现file系统。以下是
一个简单的Perl脚本，用于Linux系统发现已挂载的file系统并
以JSON格式输出，其中包含file系统名称和类型。一种使用方式
是将其作为键为"vfs.fs.discovery\_perl"的UserParameter：

```{.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";
```
其输出示例如下（为清晰起见已重新格式化）。自定义发现检查的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"  }
]
```
然后，在发现规则的"Filter"字段中，我们可以指定
"{\#FSTYPE}"作为宏，"rootfs|ext3"作为正则表达式。

::: noteclassic
使用自定义LLD规则时，不必使用FSNAME/FSTYPE作为宏名称，
可以自由使用任何喜欢的名称。如果使用JSONPath，
则LLD行将是一个array元素，可以是object，
但也可以是另一个array或值。

:::

请注意，如果使用用户参数，返回值限制为16MB。
更多详情，请参阅[返回值数据限制](/manual/discovery/low_level_discovery/notes#返回值数据限制)。

[comment]: # ({/ddf73092-5a4f43c4})
