7.5. 使用名称的 Pipe 替换日志文件

许多管理员想要通过日志数据进行一些特殊配置或操作,例如配置日志以仅记录特定事件。这无法使用标准的 Directory 服务器日志文件配置文件属性,但通过将日志数据发送到命名管道,然后使用另一个脚本来处理数据。对日志使用命名管道简化了这些特殊任务,如下所示:

  • 记录某些事件,如来自特定用户或 IP 地址的绑定尝试或连接失败
  • 与特定正则表达式模式匹配的日志记录条目
  • 将日志保持到特定的长度(仅限最后的几行)
  • 在事件发生时发送通知(如电子邮件)

使用管道替换日志文件可提高性能,特别是对于具有高操作率的服务器。

命名管道与使用脚本从日志中提取数据,因为日志缓冲区中如何处理数据。

如果日志缓冲了,服务器性能很好,但重要的数据不会在事件发生后马上写入磁盘(日志文件)。如果服务器崩溃出现问题,则在将数据写入磁盘之前,它可能会在数据写入磁盘前崩溃 - 也没有用于提取脚本的数据。

如果没有缓冲日志[1]写入操作会在磁盘中清除到磁盘,从而导致大量磁盘 I/O 和性能下降。

使用管道替换日志磁盘文件具有缓冲优势,因为管道读取的脚本可以将内存中传入的日志数据(通过简单脚本无法缓冲)。

第 9.4 节 “ds-logpipe.py” 中涵盖了脚本的用法和选项详情。基本格式为: ds-logpipe.py/path/to/named_pipe--userpipe_user--maxlinesnumber--serverpidfilefile.pid--serverpidPID--servertimeout --plugin=/path/to/plugin.pypluginfile.arg=value

7.5.1. 使用 Named Pipe 进行日志记录

Directory 服务器实例可以通过运行命名管道日志脚本并提供管道的名称,即可将命名管道用于其日志记录。(如果服务器已在运行,则必须重新打开日志,但不需要配置。)

# ds-logpipe.py /var/log/dirsrv/slapd-example/access

以这种方式运行 ds-logpipe.py 具有简单且不需要更改目录服务器配置的优点。这可用于快速调试或监控,特别是在查找特定类型的事件时。

如果 Directory 服务器实例经常或永久使用命名的管道而不是记录一个真实文件,那么可以重新配置实例以创建管道并将其用于记录(与日志文件默认这样做)。

需要为实例配置配置三个内容:

  • 要使用的日志文件必须改为管道(nsslapd-*log,其中 * 可访问、错误或审核)[2],根据所配置的日志类型而定。
  • 应禁用缓冲,因为脚本已经缓冲了日志条目(nsslapd-*log-logbuffering)
  • 日志轮转应该被禁用,因此服务器不会尝试轮转命名管道(nsslapd-*log-maxlogsperdirnsslapd-*log-logpirationtimensslapd-*log-logrotation

这些配置更改可以在 Directory Server 控制台中或使用 ldapmodify 进行。

例如,这会切换日志 来访问。pipe:

# ldapmodify -D "cn=Directory Manager" -W -p 389 -h server.example.com -x

dn: cn=config
changetype: modify
replace: nsslapd-accesslog
nsslapd-accesslog: /var/log/dirsrv/slapd-instance/access.pipe
-
replace: nsslapd-accesslog-logbuffering
nsslapd-accesslog-logbuffering: off
-
replace: nsslapd-accesslog-maxlogsperdir
nsslapd-accesslog-maxlogsperdir: 1
-
replace: nsslapd-accesslog-logexpirationtime
nsslapd-accesslog-logexpirationtime: -1
-
replace: nsslapd-accesslog-logrotationtime
nsslapd-accesslog-logrotationtime: -1
注意

进行这些更改可让服务器关闭当前日志文件并立即切换到命名管道。这对调试正在运行的服务器以及特定消息的日志输出非常有用。

7.5.2. 使用服务器启动 Named Pipe

命名的管道可以通过编辑实例的 init 脚本配置文件来启动和关闭 Directory Server 实例。

注意

命名 pipe 脚本必须在实例的 dse.ldif 文件中特别配置,然后才能在服务器启动时调用。

  1. 打开服务器系统的实例配置文件。

    /etc/sysconfig/dirsrv-instance_name
    警告

    不要编辑 /etc/sysconfig/dirsrv 文件。

  2. 在文件的末尾,会有一个包含以下内容的行:

    # Put custom instance specific settings below here.

    在该行的下面,插入 ds-logpipe.py 命令以在服务器启动时启动。例如:

    # only keep the last 1000 lines of the error log
    python /usr/bin/ds-logpipe.py /var/log/dirsrv/slapd-example/errors.pipe -m 1000 -u dirsrv -s /var/run/dirsrv/slapd-example.pid > /var/log/dirsrv/slapd-example/errors &
    
    # only log failed binds
    python /usr/bin/ds-logpipe.py /var/log/dirsrv/slapd-example/access.pipe -u dirsrv -s /var/run/dirsrv/slapd-example.pid --plugin=/usr/share/dirsrv/data/failedbinds.py failedbinds.logfile=/var/log/dirsrv/slapd-example/access.failedbinds &
    注意

    -s 选项指定要将其 PID 写入的 .pid 文件,并将脚本设置为在服务器进程启动和停止。

7.5.3. 使用带有 Named Pipe Log 的插件

可以调用插件来从命名管道读取日志数据,并在其上执行一些操作。使用带有命名 pipe log 脚本的插件有一些注意事项:

  • 对于从命名管道读取的每一行调用插件函数。
  • 插件功能必须是 Python 脚本,且必须以 .py 结尾。
  • 所有插件参数都会在命令行中传递给命名 pipe log 脚本。
  • 可以针对加载插件时指定预协作功能。
  • 可以为脚本退出时调用 post-operation 功能。

7.5.3.1. 使用 Named Pipe Log Script 载入插件

有两个选项 ds-logpipe.py 用于插件:

  • plugin 选项提供插件文件的路径(必须是 Python 脚本,且必须以 .py结尾)。
  • plugin.arg 选项将插件参数传递给命名的管道日志脚本。插件文件名(没有 .py 扩展名)是 插件,且插件中允许的任何参数都可以是 arg

例如:

ds-logpipe.py /var/log/dirsrc/slapd-example/errors.pipe --plugin=/usr/share/dirsrv/data/example-funct.py example-funct.regex="warning" > warnings.txt

如果为同一参数传递多个值,则它们将转换为插件字典中的值列表。例如,此脚本为 arg1 提供两个值:

--plugin=/path/to/pluginname.py pluginname.arg1=foo pluginname.arg1=bar pluginname.arg2=baz

在插件中,这会转换为:

{'arg1': ['foo', 'bar'],
 'arg2': 'baz'}

这是一个 Python 字典 对象,具有两个键。第一个键是字符串 arg1,其值是一个 Python 列表对象,它包含两个元素,即字符串 foobar。第二个键是字符串 arg2,其值是字符串 baz。如果参数只有一个值,它将保留为简单字符串。单个参数名称的多个值将转换为字符串列表。

7.5.3.2. 写入插件以用于 Named Pipe 日志转发脚本

ds-logpipe.py 命令需要最多有三个插件: 插件()、 pre()post ()。

任何与 ds-logpipe.py 命令一起使用的插件都必须指定 插件 功能。

插件() 功能针对日志数据中的每一行执行,而在脚本启动和停止时 预()post() 函数将运行。

每个函数都可以定义任何参数,然后使用 plugin.arg 选项将这些参数传递给脚本。另外,每个函数都可以自行定义返回值和操作。

例 7.8. 简单 Named Pipe Log Plug-in

def pre(myargs):
    retval = True
    myarg = myargs['argname']
    if isinstance(myarg, list): # handle list of values
    else: # handle single value
    if bad_problem:
        retval = False
    return retval

def plugin(line):
    retval = True
    # do something with line
    if something_is_bogus:
        retval = False
    return retval

def post(): # no arguments
    # do something
    # no return value


[1] 在访问日志中禁用日志缓冲时,服务器性能将会受到影响,当错误日志上有变化的日志级别或审计日志中。
[2] 默认情况下不启用审计日志,因此必须使用命名管道替换它之前启用此日志。