日志文件的作用
日志文件用于记录linux系统的各种运行信息的文件,相当于linux主机的日记,不同的日志文件记载了不同类型的信息,如Linux内核消息、用户登录事件、程序错误等。日志文件对于诊断和解决问题很有帮助,因为linux运行的程序通常把系统的消息和错误写入对应的日志文件,这样系统可以有据可查, 此外,当主机遭受攻击时,日志文件还可以帮助寻找攻击者留下的痕迹。
查看大日志文件
- 如果文件比较小的话,使用 vim 或者cat 直接查看,如果文件比较大的话,使用 Vim 会直接卡死。
2.如果想要查看正在滚动的日志文件。这个命令可以查看大文件。
tail -f file
Ctrl + c 终止 tail 命令
Ctrl + s 暂停 tail 命令
Ctrl + q 继续 tail 命令
3.如果文件比较大的话,也可以使用 less 命令
less file
但是使用上述命令的坏处是,默认打开的位置在第一行,并且当切换到实时滚动模式(按 F ,实现效果类似 tail -f 效果 )或者想要滚动到最底部的时候(按 G ),会卡在计算行数一段时间。如果卡的时间比较长的话,可以直接按 Ctrl + c ,取消计算行数。 我更推荐打开文件的时候使用 -n :不计算行号(打开大文件的时候很有用)。
less -n file
less +G -n file // 打开文件的时候,直接定位到文件的最底部,默认情况下是在首行
less +F -n file // 打开文件的时候,使用实时滚动模式,Ctrl + c 退出实时滚动模式,按 F 切回实时滚动模式
less +1000g -n file // 直接定位到第 1000 行,一般你提前通过 grep 命令,定位到行数后,再使用这个命令
less +50p -n file // 直接定位到 50% 的位置
在使用less的时候可以使用=查看文件显示内容
[root@cpgl log]# less yum.log #之后按=
yum.log lines 1-24/53 byte 1437/3180 45% (press RETURN)
当前屏幕显示1-24行/该文件一共有53行,该文件一共有3180 byte , 当前位置在文件的 45% 处。
不使用 -n 的坏处是:当你使用 = 的时候,会计算出当前光标所在的位置,但是务必记得,大文件计算行数会阻塞一段时间
当然如果文件比较小,你想在使用 less 打开文件,并显示文件行数的话,可以使用 :
less -N file
4.如果你已经知道日志输出的关键字的话,使用 grep , 通常需要打印关键字前后的日志。
grep 'key word' log.txt -A 20 // 列出包括匹配行之后 20 的行。
grep 'key word' log.txt -B 20 // 列出包括匹配行之前 20 的行。
grep 'key word' log.txt -C 20 // 列出包括匹配行前后各 20 行。
大文件的话,grep 出来的数据比较多的话,你可以和 less 一起使用
grep 'world' copy.log | less
5.有时候需要将 tail 和 less 命令结合起来使用
tail -n +10000 | less // 从第 10000 开始,使用 less 查看。
tail -n 10000 | less // 查看倒数第 1000 行到文件最后的数据。
6.切割文件 有时候想把一个大文件进行分割成多个小文件.(使用split 的时候,也是蛮耗时的,但是这里仍然提供一种解决方法吧) 按文件大小分割:
split -b 600m copy.log
分割后的文件默认是以 x 开头,例如我上述命令分割后文件为:
$ ls x* // 这里 * 是通配符,即列出以 x 开头的文件。
xae xad xac xab xaa
当然你可以按行数分割,具体的命令格式如下 :
split [选项]... [要切割的文件] [输出文件前缀] // 输出文件前缀为可选项
-a, --suffix-length=N | 使用长度为 N 的后缀 (默认 2)
-b, --bytes=SIZE | 设置输出文件的大小。支持单位:m,k
-C, --line-bytes=SIZE | 设置输出文件的最大行数。与 -b 类似,但会尽量维持每行的完整性
-d, --numeric-suffixes | 使用数字后缀代替字母
-l, --lines=NUMBER | 设备输出文件的行数
-help | 显示版本信息
-version | 输出版本信息
7.如果你已经知道需要的内容在第几行,但是想要显示指定行数之前或者之后的行。例如你想显示 499999900 到 500000000 这100 行的内容。 推荐使用这个方法
head -500000000 file | tail -100
其中 head -500000000 : 显示文件的前 500000000 行。
tail -100 :显示最后 100行。 两者结合起来就是在前 500000000 行中显示后 100 行,即显示 499999900 到 500000000 这100 行的内容。
或者使用 sed 命令:
sed -n '500000000q;499999900,500000000p' file
其中 -n 与 p : 表示只打印符合条件的行。 500000000q; : 表示当执行到第 500000000 行的时候停止执行。 如果不使用 500000000q; sed 默认会浏览整个文件。 499999900,500000000 : 表示499999900 到 500000000 行。其中 , 逗号表示范围。 整体结合起来就是打印 499999900 到 500000000 行,但是执行到第 500000000 行就不要再执行了。
或者使用 awk 命令
awk 'NR>=49999991 && NR<=50000000{print} NR==50000001{exit}' file
三者的执行效率
time (head -500000000 copy.log | tail -100) > /dev/null
real 0m9.456s
user 0m8.854s
sys 0m3.501s
time (sed -n '500000000q;499999900,500000000p' copy.log) > /dev/null
real 0m25.968s
user 0m25.111s
sys 0m0.833s
time (awk 'NR>=499999900&& NR<=500000000{print} NR==500000001{exit}' copy.log) > /dev/null
real 1m4.743s
user 1m3.824s
sys 0m0.906s
与其说是查看大日志文件的方法,不如说是将 grep/awk/sed/head/less/tail 多个命令结合起来的方法。
其实最重要的不是怎么看大文件,还是在程序运行时候,就要对日志文件进行归档整理,例如,每天一次归档,或者每满 500M 就归档。 当然大公司会用例如 ELK 之类的日志处理系统。
常见的日志种类
内核及系统日志
主配置文件/etc/rsyslog.conf
日志默认存放目录 /var/log
下面是常见的日志说明
- Messages 内核消息及各种应用程序的公共日志信息,包括启动、I/O错误、 网络错误
- cron 记录crond计划任务服务执行情况
- Secure 用户认证相关的安全事件信息
- Dmesg 引导过程中的各种时间信息
- maillog 进入或发出系统的电子邮件活动
- lastlog 每个用户最近的登录事件
- wtmp 每个用户登录注销及系统启动和停机事件
- btmp 失败的、错误的登录尝试及验证事件
- yum.log 包含使用yum安装的软件包信息
- boot.log 包含系统启动时的日志
用户日志
用于记录Linux系统用户登录及退出系统的相关信息,包括用户名、登录的终端、登录时间、来源主机、正在使用的进程操作等。
存放位置: /var/log/wtmp. /var/log/btmp、 /var/log/lastlog
查询命令: users、who、w、last、 lastlog、 lastb等
users: 只是简单的输出当前登录的用户名, 每个显示的用户名对应一个会话。
who: 报告当前登录到系统的每个用户的信息,包括用户名,终端,登录日期,远程主机
w: 显示当前操作系统的每个用户及其远程所运行的进程信息
last: 用于查询成功登录到系统的用户记录,最近的登录情况在最前面。 通过last命令可以及时掌握Linux主机的登录情况,若发现未经授权的用户登陆过,则表示当前主机可能已被入侵。
-a :把从何处登录系统的主机名称或IP地址,显示在最后一行
-d :将IP地址转换成主机名称
-f :记录指定文件
-R :不显示登入系统的主机名称或IP地址
-x :显示系统关闭,重新开机,以及执行等级的改变等
-n : n代表数字,表示最近n次登录的记录
lastlog :用于显示系统中所有用户最近一次登录信息
lastb :用于显显用户错误的登录列表,此指令可以发现系统的登录异常。如登录的用户名错误,密码不正确等情况都会记录在案,登录失败的情况属于安全事件,因此消失可能有人在尝试破解密码。除了使用lastb命令以外,可以直接从安全日志文件/var/log/secure中获得相关信息。
ac: 查看用户连接时间
-p :查看每个用户的连接时间
-a :查看所有用户的连接时间
-d :查看用户每天的连接时间
程序日志
有些应用程序会选择独立管理一份日志文件 ,而不是交给rsyslog服务管理,用于记录本程序运行过程中的各种事件信息。于这些程序只负责管理自己的日志文件,因此不同程序所使用的日志记录格式也会存在较大的差异。
一般yum安装的应用,日志还是在/var/log/目录下面,可能有自己专属的目录,不过一般是可以修改日志位置的,二进制编译一般是编译时候指定的。
rsyslog配置
Linux日志机制的核心是rsyslog守护进程,该服务负责监听Linux下的日志信息,并把日志信息追加到对应的日志文件中,一般在/var/log目录下。它还可以把日志信息通过网络协议发送到另一台Linux服务器上,或者将日志存储在MySQL或Oracle等数据库中。本文将简要介绍一下rsyslog的配置文件的配置,以及如何使用logrotate进行日志滚动。
rsyslog的配置文件为/etc/rsyslog.conf和/etc/rsyslog.d/目录内的文件。 rsyslog.conf文件配置了rsyslog守护进程在哪里保存日志信息。
[root@cpgl log]# grep -Ev "^$|^#" /etc/rsyslog.conf
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command) #加载imuxsock模块
$ModLoad imjournal # provides access to the systemd journal #加载imjournal模块
$WorkDirectory /var/lib/rsyslog
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat #默认模板RSYSLOG_TraditionalFileFormat
$IncludeConfig /etc/rsyslog.d/*.conf
$OmitLocalLogging on
$IMJournalStateFile imjournal.state
*.info;mail.none;authpriv.none;cron.none /var/log/messages
#表示info级别的任何消息都发送到/var/log/messages日志文件,但邮件系统、验证系统和计划任务不发送(none表示禁止)
authpriv.* /var/log/secure
#认证信息发送到/var/log/secure
mail.* -/var/log/maillog
#邮件系统发送到/var/log/maillog
cron.* /var/log/cron
#cron.* /var/log/cron 表示所有级别的cron信息发到/var/log/cron文件
*.emerg :omusrmsg:*
#*.emerg * 表示emerg错误级别(危险状态)的所有消息类型发给所有用户
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log
其余配置
#$ModLoad imudp.so #加载imudp模块支持udp
#$UDPServerRun 514 # 允许514端口接收使用UDP协议转发过来的日志
#$ModLoad imtcp.so #加载imtcp模块支持tcp
#$InputTCPServerRun 514 # 允许514端口接收使用TCP协议转发过来的日志
rsyslog配置的规则是(选择器+动作)
每个规则行由两部分组成,selector部分和action部分,这两部分由一个或多个空格或tab分隔,selector部分指定源和日志等级,action部分指定对应的操作。
选择器(SELECTORS)
selector也由两部分组成,消息源和日志级别,由点号.
分隔。第一部分为消息源或称为日志设施,第二部分为日志级别。 下面给出一个rsyslog.conf的例子:
- 消息类型
auth(security), authpriv: 授权和安全相关的消息
kern: 来自Linux内核的消息
mail: 由mail子系统产生的消息
cron: cron守护进程相关的信息
daemon: 守护进程产生的信息
news: 网络消息子系统
lpr: 打印相关的日志信息
user: 用户进程相关的信息
uucp: unix to unix copy, unix主机之间相关的通讯
local0 to local7: 保留,本地使用
- 日志错误级别
日志错误级别错误级别:(8级)debug,info,notice,warning|warn;err|error;crit,alert,emerg|panic
根据日志信息的重要程度不同,分为不同的级别 **数字级别越小,优先级越高,消息越重要
级别 英文表示 意义
0 EMERG(紧急) 导致主机系统不可用的情况
1 ALERT(警告) 必须马上采取解决措施
2 CRIT 严重 比较严重的情况
3 ERR 错误 运行出现错误
4 WARNING 提醒 提醒用户的重要事件
5 NOTICE 注意 不会儿影响系统,提醒用户
6 INFO 信息 一般信息
7 DEBUG 调式 程序调式
8 None 没有 不做记录
- 日志级别设置
.xxx: 表示大于等于xxx级别的信息
.=xxx:表示等于xxx级别的信息
.!xxx:表示在xxx之外的等级的信息
选择器使用注意事项
#例子1
mail.crit,*.err /var/log/syslog_err.log
# 这样的情况,最终的结果还是会把mail的err级别日志输出到syslog_err.log
#例子2
mail.!warn /var/log/mail.log
# 看起来是将mail的warn以下级别的日志输出到/var/log/mail.log,其实不然,你会发现你什么也得不到。
# 官方的解释是,感叹号(就是形似这个的符号 ==> !) 就是个过滤器,你得先有东西,才能去过去,比如:
mail.*;mail.!warn
动作(ACTION)
action是规则描述的一部分,规则用于处理消息。总的来说,消息内容被写到一种日志文件上,但也可以执行其他动作,比如写到数据库表中或转发到其他主机。
动作域:file,user,console,@remote_ip
#忽略,丢弃
local3.* ~ # 忽略所有local3类型的所有级别的日志
#执行脚本
local3.* ^/tmp/a.sh # ^号后跟可执行脚本或程序的绝对路径
#过滤日志, 由:号开头
:msg, contains, “error” /var/log/error.log
:msg, contains, “error” ~ # 忽略包含error的日志
:msg, contains, “user nagios” ~
:msg, contains, “user kadefor” ~
:msg, contains, “module-alsa-sink.c: ALSA woke us up to write new data to the device, but there was actually nothing to write” ~
local3.* ~
& ~ # 忽略所有的日志
转发到远程机器
有3种方式转发消息:
- 传统方式的UDP传输,有损耗
- 基于TCP明文的传输,只在特定情况下丢失信息,并被广泛使用
- RELP传输,不会丢失信息,但只在rsyslogd 3.15.0及以上版本中可用
写法:
- UDP 在主机名前加"@"
- TCP 在主机名前加"@@"
- RELP 在主机名前加":omrelp:"
例:
*.* @192.168.0.1 #将所有日志信息通过UDP协议发送到192.168.0.1
如果要修改为非514的端口, 需要设置selinux
只要在rsyslog.conf中加入
*.* @192.168.0.10 #UDP
*.* @192.168.0.10:10514 #带端口号
*.* @@192.168.0.10 #TCP
*.* :omrelp:192.168.0.10 #RELP
模板(template)
rsyslog属性
常用的rsyslog属性,其他额外的信息可以使用man rsyslog.conf 命令去查看rsyslog.conf手册。
msg: 即消息源进程调用syslog家族函数,所传递的文本信息
rawmsg: 从套接字接收到的消息完全相同。应该对调试有用。
HOSTNAME:来自消息的主机名
FROMHOST:接收到消息的系统的主机名(在中继链中,这是直接在我们面前的系统,但 不一定原始发件者)。
syslogtag:来自消息的标签,通常来说,要么是消息源进程的用户名。
programname:标签的“静态”部分,通常%programname%是输出的值和%syslogtag%是相同的。
PRI:消息的下划线部分-未解码(单值)
syslogseverity-text:消息等级的严重性-文本形式
timegenerated:接收消息时的时间戳。
timereported:消息中的时间戳。 解析精度取决于消息中提供的内容(在大多数情况下,仅精确到秒)
TIMESTAMP:timereported的别名
PROTOCOL-VERSION:协议版本
以$符号开头的属性是所谓的系统属性。 这些不是消息产生的,而是Linux系统内部产生的。
$NOW当前日期戳,格式为YYYY-MM-DD
$YEAR当前年份(4位数字)
$MONTH当前月份(2位数字)
$DAY月的当前日期(两位数)
$HOUR当前的军事时数(24小时)(2位数字)
$MINUTE当前分钟(2位数字)
模板允许你指定日志信息的格式,可用于生成动态文件名,或在规则中使用。其定义如下所示,其中TEMPLATE_NAME是模板的名字,PROPERTY是rsyslog本身支持的一些属性参数。
#示例模板
$template TEMPLATE_NAME,"text %PROPERTY% more text", [OPTION]
#设置模板名为 myFormat 格式为 %rawmsg%\n
$template myFormat,”%rawmsg%\n”
新版定义模板的方式
#自定义模板
template(name="myFormat" type="list"){
property(name="$now")
constant(value=" ")
property(name="timegenerated")
constant(value=" ")
property(name="hostname")
constant(value=" ")
property(name="programname")
constant(value=" ")
property(name="msg" spifno1stsp="on")
property(name="msg" droplastlf="on")
constant(value="\n")
}
模板定义及使用的例子
$template DynamicFile,"/var/log/test_logs/%timegenerated%-test.log"
*.* ?DynamicFile
规则中绑定模板
在日志规则的动作字段,按照如下所示,添加一个:<模板名称>,其他步骤跟上面一个示例一致。
local1.* /var/log/test.log:myFormat #myFormat这个就是设置的模板,前面必须定义
当然下面还有一条等效的规则,如下所示
local1.* action(type="omfile" file="/varlog/test.log" template="myFormat")
输出模板
输出模板为用户可能想要的输出类型提供了保护,在规则中使用前要先定义.其定义如下所示,其中NAME指定输出频道的名称,FILENAME指定输出文件,MAXSIZE指定日志文件的大小,单位是bytes, ACTION指定日志文件到达MAX_SIZE时的操作。
$outchannel NAME, FILE_NAME, MAX_SIZE, ACTION
在规则中使用输出频道按照如下的格式:
FILTER :omfile:$NAME
下面给出使用输出频道的一个例子:
$outchannel log_rotation, /var/log/test_log.log, 104857600, /home/aaa/log_rotation_script
*.* :omfile:$log_rotation
日志测试
logger -p local3.info 'KadeFor is testing the rsyslog and logger' #logger 命令用于产生日志
logrotate配置
日志转储(rotate)
储方式可以设为每年转储、每月转储、每周转储、达到一定大小转储。
在Linux系统,经常使用**“logrotate”工具进行日志转储,结合cron**计划任务,可以轻松
实现日志文件的转储。转储方式的设置由**“/etc/logrotate.conf”**配置文件控制
[root@cpgl ~]# cat /etc/logrotate.conf
# see "man logrotate" for details
# rotate log files weekly
weekly #设置每周转储
# keep 4 weeks worth of backlogs
rotate 4 #最多转储4次
# create new (empty) log files after rotating old ones
create #当转储后文件不存储时创建它
# use date as a suffix of the rotated file
dateext # 指定切割文件的后缀名,这里以日期为后缀名
# uncomment this if you want your log files compressed
#compress #以压缩方式转储
# RPM packages drop log rotation information into this directory
include /etc/logrotate.d #其他日志文件的转储方式,包含在该目录下
#minsize 1M # 文件容量超过这个值时才进行切割
# no packages own wtmp and btmp -- we'll rotate them here
/var/log/wtmp {
monthly #每月转储
create 0664 root utmp #转储后文件不存在时创建它,文件所有者为root所属组为utmp,对应的权限为0664
minsize 1M # 文件容量超过1M时才进行切割
rotate 1 #转储一次
}
/var/log/btmp {
missingok #如果日志丢失, 不报错
monthly
create 0600 root utmp
rotate 1
}
# system-specific logs may be also be configured here.
转储(rotate)例子
#为/var/log/httpd/access.log和/var/log/httpd/error.log日志设置转储参数。转储5次,转储时发送邮件给root@localhost用户,当日志文件达到100KB时才转储,转储后重启httpd服务
/var/log/httpd/access.log /var/log/http/error.log{
rotate 5
mail root@localhost
size=100k
sharedscripts #表示切换时脚本只执行一次
systemctl restart httpd
endscript
}
#rsyslog的日志文件每天被rotated,保留7份旧的日志。其他的日志文件每周进行一次rotate,并保留4份旧的日志。
/var/log/mail.info
/var/log/mail.warn
/var/log/mail.err
/var/log/mail.log
/var/log/daemon.log
/var/log/kern.log
/var/log/auth.log
/var/log/user.log
/var/log/lpr.log
/var/log/cron.log
/var/log/debug
/var/log/messages # 指定多个文件, 如果有特殊字符需要用单引号
{
rotate 4
weekly
missingok #如果日志丢失, 不报错
notifempty
compress # 全局设置, 压缩
delaycompress
sharedscripts # 共享脚本. 下面的postrotate脚本只运行一次.
postrotate # 表示rotate后执行的脚本
systemctl restart rsyslog
endscript #表示脚本结束
}
自定义日志处理
#将所有类型错误级别为info的日志转储到/var/log/test.log日志文件中,并设置/var/log/test.log达到50KB后进行转储,转储10次,转储时压缩,转储后重启syslog服务
#1.修改/etc/syslog.conf文件使得如下:
[root@cpgl log]#tail -1 /etc/rsyslog.conf //查看该文件的最后一行
*.info /var/log/test.log
#2.重启rsyslog服务:
[root@cpgl log]# systemctl restart rsyslog
#3.创建/etc/logrotate.d/test.log日志转储参数配置文件
[root@helle ~]# cat /etc/logrotate.d/test.log
/var/log/test.log{
rotate 10
size = 50k
compress
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
# 可查看/etc/logrotate.d/下的配置文件
endscript
}
#4.查看文件/etc/cron.daily/logrotate确保如下
[root@cpgl cron.daily]# cat /etc/cron.daily/logrotate
#!/bin/sh
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
#查看转储后的文件
[root@cpgl log]# pwd
/var/log
[root@cpgl log]# ls test.log* #结果等要转储的时候会发现压缩文件和原本的test.log文件
test.log test.log-20220924.gz
转储(rotate)测试
logrotate -f /etc/logrotate.conf –强制轮转
logrotate -vf /etc/logrotate.conf –再加一个-v参数查看轮转的过程
日志发送与接收
配置服务端(接收)
#配置服务端(接收)
vi /etc/rsyslog.conf #在文件开始加上,同时确保514端口能够被客户端用tcp访问
$ModLoad imtcp.so # needs to be done just once #使用tcp方式
$InputTCPMaxSessions 500 # tcp接收连接数为500个
$InputTCPServerRun 514 # tcp接收信息的端口
$template logformat,”%TIMESTAMP:::date-mysql% %FROMHOST-IP%%msg%\n” # 定义一个名为logformat模板, 为信息加上日志时间
$template DynFile,”/var/log/tlog%$year%%$month%%$day%.log” # 定义日志文件的名称,按照年月日
:rawmsg, contains, “sdns_log” ?DynFile;logformat # 把rawmsg(也可以使用msg)日志中包含sdns_log标志的信息写到DynFile定义的日志文件里
:rawmsg, contains, “sdns_log” ~ # 这个表示丢弃包含sdns_log标志的信息, 一般都加上它, 以免多个日志文件记录重复的日志
———————————————————————
补充:
如果要把不同服务器发送过来的日志保存到不同的文件, 可以这样操作:
:fromhost-ip, isequal, “192.168.0.160″ /var/log/host160.log
:FROMHOST-IP, isequal, “192.168.0.161″ /var/log/host161.log
:FROMHOST-IP, startswith, “192.168.1.” /var/log/network1.log
:FROMHOST-IP, startswith, “192.168.2.” /var/log/network2.log
配置客户端(发送)
#配置客户端(发送)
vi /etc/rsyslog.conf #在文件开始加上
#把包含sdns_log的信息通过tcp发到xxx @@表示tcp @表示udp
:rawmsg, contains, “sdns_log” @@xxx # 默认514端口
#这个表示丢弃包含sdns_log标志的信息,防止这个信息写到本机的/var/log/message
:rawmsg, contains, “sdns_log” ~
#测试
———————————————————————
在客户端上执行
logger -p user.info “sdns_log 34334″
在服务端的/var/log/目录里是否有tlog*日志产生