Unix/Linux编程:syslog进程与日志输出

守护进程: 在后台运行而且不和任何控制终端关联的进程

Linux系统日志

服务器的调试和维护的都需要一个专业的日志系统。Linux提供一个守护进程来处理系统日志----syslogd(不过现在Linux系统上使用的一般是它的升级版----rsyslogd)。

syslog 工具提供了一个集中式日志工具,系统中的所有应用程序都可以使用这个工具来记
录日志消息:

Unix/Linux编程:syslog进程与日志输出_第1张图片

  • syslog 工具有两个主要组件:syslogd daemon 和 syslog(3)库函数
  • System Log daemon syslogd 从两个不同的源接收日志消息:
    • 一个是Unix domian socket /dev/log,它保存本地产生的信息
    • 一个是Internet domain socket(UNP 端口 514,如果启用的话),它保存通过 TCP/IP 网络发送的消息。(在其他一些 UNIX 实现中,syslog socket 位于/var/run/log。
  • 每条由syslogd处理的消息都具备几个特性:
    • facility,指定产生消息的程序类型
    • level,指定消息的严重程度(优先级)
  • syslogd daemon会检查每条消息的facility 和 level,然后根据一个相关配置文件/etc/syslog.conf 中的指令将消息传递到几个可能目的地中的一个。
    • 可能的目的地包括终端或虚拟控制台、磁盘文件、FIFO、一个或多个(或所有)登录过的用户以及位于另一个系统上的通过 TCP/IP 网络连接的进程(通常是另一个 syslogd daemon)。
    • (将消息发送到另一个系统上的进程有助于通过将多个系统中的日志
      信息集中到一个位置以降低管理负担。)
    • 一条消息可以被发送到多个目的地(或不发送到任何目的地),具备不同的 facility 和 level 组合的消息可以被发送到不同的目的地或不同的目的地实例(即不同的控制台、不同的磁盘文件等)。
    • 通过 TCP/IP 网络将 syslog 消息发送到另一个系统还有助于发现系统非法入侵。非法入侵通常会在系统日志中留下踪迹,但攻击者通常会删除日志记录以掩盖他们的行为。有了远程日志记录之后,攻击者就需要侵入另一个系统才能删除日志记录。
  • 通常,任意进程都可以使用 syslog(3)库函数来记录消息。这个函数会使用传入的参数以标准的格式构建一条消息,然后将这条消息写入/dev/log socket 以供 syslogd 读取
  • /dev/log 中的消息的另一个来源是 Kernel Log daemon klogd,它会收集内核日志消息(内核使用 printk()函数生成的消息)。
    • 这些消息的收集可以通过两个等价的 Linux 特有的接口中的一个来完成(即/proc/kmsg 文件和 syslog(2)系统调用),然后使用 syslog(3)库函数将它们写入/dev/log
    • 尽管 syslog(2)和 syslog(3)的名称相同,但它们执行的任务是不同的。glibc 提供了一个调用 syslog(2)的接口,其名称为 klogctl()。

syslogd守护进程

Unix系统中的syslogd守护进程通常由某个系统初始化脚本启动,而且在系统工作期间一直运行。 源自Berkeleysyslogd实现在启动时执行以下步骤

(1) 读取配置文件

  • /etc/syslog.conf指定本守护进程可能收取的各种日志信息应该如何处理

CentOS6.5之前,配置文件为/etc/syslog.conf,从CentOS6.5之后,配置文件名变更为/etc/rsyslog.conf

  • 这些消息可能被添加到一个文件(/dev/console文件是一个特例,它把消息写到控制台上),或者被写到指定用户的登录窗口(如果该用户已经登录到本守护进程所在系统中),或者被转发给另一个主机上的syslogd进程

(2)创建一个Unix数据报套接字,给它捆绑路径名/var/run/log或者/dev/log
(3) 创建一个UDB套接字,捆绑514端口
(4)打开路径名/dev/log。来自内核中的任何出错作为=消息

rsyslogd守护进程

在CentOS6.x中日志服务已经由rsyslogd取代了原先的syslogd服务rsyslog 是一个 syslogd 的多线程增强版,其配置语法与syslogd的配置文件一致。

rsyslogd 相比 syslogd 具有一些新的特点:

  • 基于TCP网络协议传输日志信息
  • 更安全的网络传输方式
  • 有日志信息的即时分析框架
  • 后台数据库
  • 在配置文件中可以写简单的逻辑判断
  • 与syslog配置文件相兼容

rsyslogd的官方网站为: rsyslog

系统中的绝大多数日志文件是由 rsyslogd 服务来统一管理的,只要各个进程将信息给予这个服务,它就会自动地把日志按照特定的格式记录到不同的日志文件中。也就是说,采用 rsyslogd 服务管理的日志文件,它们的格式应该是统一的。

rsyslogd守护进程既能接收用户进程输出的日志,又能接收内核日志

  • 用户进程是通过调用syslog函数生成系统日志的。该函数将日志输出到一个unix本地域socket类型的文件/dev/log中。rsyslogd则监听该文件获取用户进程的输出。
  • 内核日志在老的系统上是通过另一个守护进程rklogd来管理的。内核日志由printk等函数打印至内核的环状缓存(ring buffer)中。环状缓存的内容直接映射到/proc/kmsg文件中。rsyslogd则通过读取该文件获取内核日志

rsyslogd守护进程在接收到用户进程会在内核输入的日志之后,会把它们输出到某些特定的日志文件

  • 调试信息保存到/var/log/debug
  • 普通信息保存到/var/log/messages
  • 内核信息保存到/var/log/kern.log

不过,具体日志如何分发,可以在rsyslogd的配置文件中配置

Unix/Linux编程:syslog进程与日志输出_第2张图片

配置文件

CentOS6.5之前,配置文件为/etc/syslog.conf,从CentOS6.5之后,配置文件名变更为/etc/rsyslog.conf

  • 该文件由不同程序或消息分类的单个条目组成,每个占一行。对每类消息提供一个选择域和一个动作域。这些域由tab隔开
    • 选择域指明消息的类型和优先级;
    • 动作域指明syslogd接收到一个与选择标准相匹配的消息时所执行的动作。

每个选项是由设备和优先级组成。当指明一个优先级时,syslogd将纪录一个拥有相同或更高优先级的消息。所以如果指明"crit",那所有标为crit、alert和emerg的消息将被纪录。每行的行动域指明当选择域选择了一个给定消息后应该把他发送到哪儿。

格式为:

​ 类型.级别;类型.级别 [TAB] 动作

  • 保留字段中的“类型(facility)”代表信息产生的源头,可以是:
    • auth 认证系统,即询问用户名和口令(不推荐使用authpriv替代)
    • authpriv: 安全和认证相关消息(私有的)
    • cron 系统定时任务cront和at产生的日志
    • daemon 某些系统的守护程序的syslog,如由in.ftpd产生的log
    • kern 内核的syslog信息
    • lpr 打印机的syslog信息
    • mail 邮件系统的syslog信息
    • mark 定时发送消息的时标程序
    • news 新闻系统的syslog信息
    • user 本地用户应用程序的syslog信息
    • uucp uucp子系统的syslog信息
    • local0…7 种本地类型的syslog信息,这些信息可以由用户来定义
    • * 代表以上各种设备
  • 保留字段中的“级别”代表信息的重要性,可以是:
    • emerg 紧急,处于Panic状态。通常应广播到所有用户;
    • alert 告警,当前状态必须立即进行纠正。例如,系统数据库崩溃;
    • crit 关键状态的警告。例如,硬件故障;
    • err 其它错误;
    • warning 警告;
    • notice 注意;非错误状态的报告,但应特别处理;
    • info 通报信息;
    • debug 调试程序时的信息;
    • none 通常调试程序时用,指示带有none级别的类型产生的信息无需送出。如*.debug;mail.none表示调试时除邮件信息外其它信息都送出。
  • “动作”(action)域指示信息发送的目的地。可以是:
    • /filename 日志文件。由绝对路径指出的文件名,此文件必须事先建立;
    • @host 远程主机; @符号后面可以是ip,也可以是域名,默认在/etc/hosts文件下loghost这个别名已经指定给了本机。
    • user1,user2 指定用户。如果指定用户已登录,那么他们将收到信息;
    • * 所有用户。所有已登录的用户都将收到信息。

Linux系统中的常见日志以及功能

日志文件是重要的系统信息文件,其中记录了许多重要的系统事件,包括用户的登录信息、系统的启动信息、系统的安全信息、邮件相关信息、各种服务相关信息等。这些信息有些非常敏感,所以在 Linux 中这些日志文件只有 root 用户可以读取。

那么,系统日志文件保存在什么地方呢?还记得 /var/ 目录吗?它是用来保存系统动态数据的目录,那么 /var/log/ 目录就是系统日志文件的保存位置。

下表列出了一些比较重要的日志文件:

日志文件 说明
/var/log/cron 记录与系统定时任务相关的曰志
/var/log/cups/ 记录打印信息的曰志
/var/log/dmesg 记录了系统在开机时内核自检的信息。也可以使用dmesg命令直接查看内核自检信息
/var/log/btmp 记录错误登陆的日志。这个文件是二进制文件,不能直接用Vi查看,而要使用lastb命令查看
/var/log/lasllog 记录系统中所有用户最后一次的登录时间的曰志。这个文件也是二进制文件.不能直接用Vi 查看。而要使用lastlog命令查看
/var/Iog/mailog 记录邮件信息的曰志
/var/log/messages 它是核心系统日志文件,其中包含了系统启动时的引导信息,以及系统运行时的其他状态消息。I/O 错误、网络错误和其他系统错误都会记录到此文件中。其他信息,比如某个人的身份切换为 root,已经用户自定义安装软件的日志,也会在这里列出。
/var/log/secure 记录验证和授权方面的倍息,只要涉及账户和密码的程序都会记录,比如系统的登录、ssh的登录、su切换用户,sudo授权,甚至添加用户和修改用户密码都会记录在这个日志文件中
/var/log/wtmp 永久记录所有用户的登陆、注销信息,同时记录系统的后动、重启、关机事件。同样,这个文件也是二进制文件.不能直接用Vi查看,而要使用last命令查看
/var/tun/ulmp 记录当前已经登录的用户的信息。这个文件会随着用户的登录和注销而不断变化,只记录当前登录用户的信息。同样,这个文件不能直接用Vi查看,而要使用w、who、users等命令查看

除系统默认的日志之外,采用 RPM 包方式安装的系统服务也会默认把日志记录在 /var/log/ 目录中(源码包安装的服务日志存放在源码包指定的目录中)。不过这些日志不是由 rsyslogd 服务来记录和管理的,而是各个服务使用自己的日志管理文档来记录自身的日志。以下介绍的日志目录在你的 Linux 上不一定存在,只有安装了相应的服务,日志才会出现:

日志 说明
/var/log/httpd/ RPM包安装的apache取务的默认日志目录
/var/log/samba/ RPM色安装的Samba服务的日志目录
/var/log/sssd/ 守护进程安全服务目录

syslog API

建立一个到系统日志的连接

  • openlog()函数建立一个到系统日志工具的连接并为后续的 syslog()调用设置默认设置
  • syslog()的调用是可选的,如果省略了这个调用,那么就会使用首次调用 syslog()时采用的默认设置来建立到日志记录工具的连接。
SYNOPSIS
       #include 

       void openlog(const char *ident, int option, int facility);

(1)ident 参数是一个指向字符串的指针:

  • syslog()输出的每条消息都会包含这个字符串,这个参数的取值通常是程序名。
  • 注意 openlog()仅仅是复制了这个指针的值。只要应用程序后面会继续调用 syslog(),那么就应该确保不会修改所引用的字符串

(2)传入 openlog()的 log_options 参数是一个位掩码,它是下面几个常量之间的 OR 值

  • LOG_CONS : 当向系统日志发送消息发生错误时将消息写入到系统控制台(/dev/console)。
  • LOG_NDELAY :
    • 立即打开到日志系统的连接(即底层的 UNIX domain socket, /dev/log)
    • 在默认情况下(LOG_ODELAY),只有在首次使用 syslog()记录消息的时候才会打开连接。
    • O_NDELAY 标记对于那些需要精确控制何时为/dev/log 分配文件描述符的程序来讲是比较有用的,如调用chroot()的程序就有这样的要求。在调用 chroot()之后,/dev/log 路径名将不再可见,因此在chroot()之前需要调用一个指定了 LOG_NDELAY 的 openlog()。
  • LOG_NOWAIT
    • 不要wait()被创建来记录日志消息的子进程
    • 在那些创建子进程来记录日志消息的实现上,当调用者创建并等待子进程时就需要使用 LOG_NOWAIT 了,这样 syslog()就不会试图等待已经被调用者销毁的子进程。
    • 在 Linux 上,LOG_NOWAIT 不起任何作用,因为在记录日志消息时不会创建子进程
  • LOG_ODELAY
    • 这个标记的作用与 LOG_NDELAY 相反——连接到日志系统的操作会被延迟至记录第一条消息时。
    • 这是默认行为,因此无需指定这个标记
  • LOG_PERROR :
    • 将消息写入标准错误和系统日志。
    • 通常,daemon进程会关闭标志错误或者将其重定向到/dev/null,这样 LOG_PERROR 就没有用了
  • LOG_PID :
    • 在每条消息中加上调用者的进程 ID。
    • 在一个创建多个子进程的服务器中使用 LOG_PID有助于区分哪个进程记录了某条特定的消息

(3)第三个参数facility是用来指定记录消息程序的类型。它让指定的配置文件,将以不同的方式来处理来自不同方式的消息。

  • LOG_AUTH ——认证系统:login、su、getty等
  • LOG_AUTHPRIV ——同LOG_AUTH,但只登录到所选择的单个用户可读的文件中
  • LOG_CRON ——cron守护进程
  • LOG_DAEMON ——其他系统守护进程,如routed
  • LOG_FTP ——文件传输协议:ftpd、tftpd
  • LOG_KERN ——内核产生的消息
  • LOG_LPR ——系统打印机缓冲池:lpr、lpd
  • LOG_MAIL ——电子邮件系统
  • LOG_NEWS ——网络新闻系统
  • LOG_SYSLOG ——由syslogd(8)产生的内部消息
  • LOG_USER ——随机用户进程产生的消息
  • LOG_UUCP ——UUCP子系统
  • LOG_LOCAL0~LOG_LOCAL7 ——为本地使用保留

记录一条日志消息

要写入一条日志消息可以调用 syslog()

SYNOPSIS
       #include 

       void syslog(int priority, const char *format, ...);

syslog函数中
(1)priority是level(级别) + facility(设置)的组合
level如下:

  • LOG_EMERG——紧急情况
  • LOG_ALERT——应该被立即改正的问题,如系统数据库破坏
  • LOG_CRIT——重要情况,如硬盘错误
  • LOG_ERR——错误
  • LOG_WARNING——警告信息
  • LOG_NOTICE——不是错误情况,但是可能需要处理
  • LOG_INFO——情报信息
  • LOG_DEBUG——包含情报的信息,通常旨在调试一个程序时使用
    (2) format:们与传入 printf()中的参数是一样的,但与 printf()不同的是这里的格式字符串不需要包含一个换行字符

关闭日志

当完成日志记录之后可以调用 closelog()来释放分配给/dev/log socket 的文件描述符

SYNOPSIS
       #include 

       void closelog(void);

过滤日志消息

程序的开发阶段可能需要输出很多调试信息,而发布之后又不需要这些调试信息了。解决这个问题的方法并不是在程序发布之后删除调试代码(因为日后可能还需要用到),而是通过setlogmask设置日志掩码,使得日志级别大于日志掩码的日志信息被系统忽略

setlogmask()函数设置了一个能过滤由 syslog()写入的消息的掩码。

NAME
       setlogmask - set log priority mask

SYNOPSIS
       #include 

       int setlogmask(int mask);

所有 level 不在当前的掩码设置中的消息都会被丢弃。默认的掩码值允许记录所有的严重性级别。

宏 LOG_MASK()创建一个能过滤特定级别的所有消息的位掩码。如下为丢弃除优先级为 LOG_ERR 以及LOG_CRIT之外的消息

setlogmask(LOG_MASK(LOG_ERR) | LOG_MASK(LOG_CRIT));

LOG_UPTO()宏创建一个能过滤特定级别以及以上的所有消息的位掩码。如下为丢弃除优先级为 LOG_ERR 以及以上之外的消息

setlogmask(LOG_UPTO(LOG_ERR));

实践

启动rsyslogd服务

1、查看服务器是否启动

$  ps aux | grep "rsyslog" | grep -v "grep"
root       1715  0.1  0.1 216396  5192 ?        Ssl  19:45   0:00 /usr/sbin/rsyslogd -n

lastb查看登录日志

[root@localhost log]#lastb
root tty1 Tue Jun 4 22:38 - 22:38 (00:00)

Linux日志文件格式分析

只要是由日志服务 rsyslogd 记录的日志文件,它们的格式就都是一样的。

日志文件的格式包含以下 4 列:

  • 事件产生的时间。
  • 产生事件的服务器的主机名。
  • 产生事件的服务名或程序名。
  • 事件的具体信息。

/var/log/secure为例,这个日志中主要记录的是用户验证和授权方面的信息

[root@localhost ~]$ vi /var/log/secure
Jun 5 03:20:46 localhost sshd[1630]:Accepted password for root from 192.168.0.104 port 4229 ssh2
# 6月5日 03:20:46 本地主机 sshd服务产生消息:接收从192.168.0.104主机的4229端口发起的ssh连接的密码
Jun 5 03:20:46 localhost sshd[1630]:pam_unix(sshd:session):session opened for user root by (uid=0)
#时间 本地主机 sshd服务中pam_unix模块产生消息:打开用户root的会话(UID为0)
Jun 5 03:25:04 localhost useradd[1661]:new group:name=bb, GID=501
#时间 本地主机 useradd命令产生消息:新建立bb组,GID为501

配置文件分析

$ cat /etc/rsyslog.conf
# ​ 类型.级别;类型.级别    [TAB]     动作
*.err;kern.debug;daemon.notice;mail.crit    [TAB]   /var/adm/messages 

这行中的“action”就是我们常关心的那个/var/adm/messages文件,输出到它的信息源头“selector”是:
*.err - 所有的一般错误信息;

  • kern.debug - 核心产生的调试信息;
  • daemon.notice - 守护进程的注意信息;
  • mail.crit - 邮件系统的关键警告信息

例如,如果想把所有邮件消息纪录到一个文件中,如下:

#Log all the mail messages in one place
mail.* /var/log/maillog

其他设备也有自己的日志。UUCP和news设备能产生许多外部消息。它把这些消息存到自己的日志(/var/log/spooler)中并把级别限为"err"或更高。例如:

# Save mail and news errors of level err and higher in aspecial file. 
uucp,news.crit /var/log/spooler

openlog、syslog、closelog

#include 

int main(int argc, char **argv) {
    openlog("zooyo", LOG_CONS | LOG_PID, 0);
    syslog(LOG_INFO,
           "This is a syslog test message generated by program %sn",
           argv[0]);
    closelog();
    return 0;
}

编译运行,然后查看

cat /var/log/messages

在这里插入图片描述

#include
#include
#include 
#define SYSNAME "wohawoha"
void Info(void)
{
	 openlog("info",LOG_PID,LOG_LOCAL5);/*注意这里的数字5与第一条里面提到的local5.*里的5必须相同,并且这个数字的范围为0--7*/
	 syslog(LOG_INFO, "hello %s","woring");
}

void Woring(void)
{
	 openlog("woring",LOG_PID,LOG_LOCAL5);
	 syslog(LOG_WARNING, "hello %s","test");
}

int main()
{
	 Info();
	 Woring();
	 closelog();
	 return 0;
}

总结

syslog工具为daemon(以及其他应用程序)提供了一种便捷的方式来将错误和其他消息记录到一个中间位置、这些消息由syslogd daemon处理,syslogd会根据syslogd.conf配置文件中的指令来重新分发消息。可以将消息重新分发到几个目标上,包括终端、磁盘文件、登录的用户以及通过 TCP/IP 网络分发到远程主机上的进程中(通常是其他 syslogd daemon)。

Linux系统日志管理

你可能感兴趣的:(Unix/Linux编程)