2.5.1 SysLogger系统日志进程
日志信息是数据库管理员获取数据库系统运行状态的有效手段。在数据库出现故障时,日志信息是非常有用的。把数据库日志信息集中输出到一个位置将极大方便管理员维护数据库系统。然而,日志输出将产生大量数据(特别是在比较高的调试级别上),单文件保存时不利于日志文件的操作。因此,在SysLogger的配置选项中可以设置日志文件的大小,SysLogger会在日志文件达到指定的大小时关闭当前日志文件,产生新的日志文件。在postgresql.conf里可以配置日志操作的相关参数:
log_destination:配置日志输出目标,根据不同的运行平台会设置不同的值,Linux下默认为stderr。
logging_collector:是否开启日志收集器,当设置为on时启动日志功能;否则,系统将不产生系统日志辅助进程。
log_directory:配置日志输出文件夹。
log_filename:配置日志文件名称命名规则。
log_rotation_size:配置日志文件大小,当前日志文件达到这个大小时会被关闭,然后创建一个新的文件来作为当前日志文件。
此外,postgresql.conf中还提供了其他配置参数,可以根据需要进行设置。
系统日志辅助进程的入口位置为SysLogger_Start函数。在SysLogger_Start函数第一次运行时,首先将调用系统函数pipe创建管道syslogPipe用于接收stderr的输出。接下来创建日志目录和文件,然后调用fork_process函数fork一个子进程来运行syslogger。成功创建子进程后,在父进程即Postmaster中用dup2系统函数将stdout和stderr重定向到日志管道的写入端,然后关闭日志管道的写入端和日志文件(Postmaster不需要再来写日志文件,stdout和stderr的输出将直接通过管道写入日志文件),最后返回子进程的PID。而在刚创建的子进程中,则关闭已创建的监听套接字,丢弃与Postmaster的共享内存的联系,最后调用SysLoggerMain函数真正进入日志进程的运行。
在SysLoggerMain函数体中,首先将对系统日志进程相关的全局变量进行赋值初始化,如记录自己的进程号、获取当前时间、进程状态标志等,若是重新启动SysLogger进程则要对stderr和管道进行重新设置。在进入系统日志进程处理流程主循环之前,需要注册信号处理函数,包括SIGHUP信号设置读取配置文件、SIGUSR1信号设置切换日志请求;记录当前日志文件所在目录、日志文件名称、本次日志文件的生成时间,并调用set_next_rotation_time函数设置下一次日志周期(即关闭当前日志文件并创建新的日志文件)的时间点。完成准备工作后,程序将进入一个无限循环,它是SysLogger的工作主体。
每一次循环将首先判断是否收到了SIGHUP信号,如收到则调用ProcessConfigFile函数重新处理配置文件,并设置相应的参数的值。之后判断配置参数Log_directory、Log_filename和当前日志文件信息是否相同,即日志文件目录和名称是否发生修改,若修改则设置全局变量rotation_requested为真,表示需要进入新的日志周期。接下来判断日志文件是否达到下一次周期时间、是否达到规定的日志文件大小限制,如果满足日志切换条件,则设置rotation_requested为真。完成上述检查后,判断rotation_requested是否为真,是则调用logfile_rotate函数创建一个新日志文件,并关闭旧的日志文件。
接下来将调用select系统函数监听日志管道的读取端,当监听到发生了数据读取事件时,调用piperead函数从日志管道的读取端中读取一定长度的数据到临时缓冲区logbuffer中。如果读取数据的长度大于0,则调用process_pipe_input函数对读取的数据进行处理,完成后跳出本次循环进入下一次循环;如果长度等于0则表明已经到达了日志管道末端,当前已没有任何进程维持着管道写入端,那么退出SysLogger进程。
process_pipe_input函数
process_pipe_input函数解析以chunk(块)为单位传送日志信息的日志管道协议,它采用save_buffer类型的全局数组saved_chunks[20]保存最多20个进程的日志信息chunk(一个save_buffer保存一个进程的chunk)直到接收完最后一个chunk,从而构成一个完整的消息后调用write_syslogger_file函数把该消息写入到日志文件中。
【责任编辑:云霞 TEL:(010)68476606】