背景
logger
是一个在Linux和Unix操作系统中使用的命令行工具,可以直接向系本地syslog
文件或远程Syslog服务器发送消息。logger
为写日志提供了不同的选项,如设置优先级、指定远程系统或指定Syslog端口。在调试
rsyslog
收发功能的时候,突然出现logger
无法向本地及远程任何地方发送消息的情况,在对该问题的排查定位中使用的手段和思路,对于深入调查linux上同类问题有一定的参考价值。
问题描述
常规使用,logger
无法给本地系统日志和远端发送消息,无显式报错,而在这之前能够正常工作。
具体复现如下:
logger -p local1.info "my name is Hanmeimei"
# -p, --priority priority_level,指定输入消息的优先级
# 在执行命令后,本地的syslog收不到信息;
排查与定位
首先排除rsyslog升级、配置等原因,因为之前一直正常运行,没人修改这些配置。
如果重启该机器,可以立即解决这个问题,
logger -p local1.info "msg"
可以正常使用。重启机器是一个重操作,代价很大,一般不作首要处理方案,需要进一步定位原因,减轻影响。我现在有3台机器都出现这个问题,我重启了2台,留下一台做对比研究使用(后分别称作对照机与问题机)。
因为logger命令本身无法直接查看,没有找到日志,暂无法追踪,要想其他办法去查——了解到可以使用strace指令跟踪logger命令的调用栈情况,如下:
-
执行
strace -f logger -p local1.info "123"
strace
介绍:
顾名思义,strace是一个可用于诊断、调试和教学的Linux用户空间跟踪器。strace底层使用内核的ptrace特性来实现其功能。
strace作为一种动态跟踪工具,能够帮助运维高效地定位进程和服务故障。这里,-f 表示跟踪由fork调用所产生的子进程,后面跟的是原始命令。
分别获取到对照机与问题机的上述指令的输出。使用Compare或者IDEA进行内容的对比:
左侧是对照机正常的输出,右侧是有问题的。通过对比,两个文件内容只有一处实质不同,即正常输出比问题机多了一行内容②,而这一行就是实际要发送的内容(“123”)。
-
问题发生在①处,正常的这里返回了0,异常的这里返回-1,(报错...
-1 ECONNREFUSED (Connection refused)
)——因为连接被拒绝,①处门都没打开,当然也就没有后面发送消息的②了。
- 综上,关键信息出现——指向了
/dev/log
,错误为:连接被拒绝!因此没有成功发出消息。我们顺藤摸瓜:这个/dev/log
是个特殊文件,它的属性是srw-rw-rw-,s代表Unix domain socket
,也称为网络套接字。
-
继续追溯到
/dev/log
与systemd-journald.socket
有关系。systemd-journald的补充:
systemd-journald
是一个收集并存储各类日志数据的系统服务。如果在启动期间存在/var/log/journal/
目录,那么日志将会被持久存储在此目录中, 否则将会临时存储在/run/log/journal/
目录中(关机即丢失)。以 "
.socket
" 为后缀的单元文件, 封装了一个用于进程间通信的套接字(socket)或管道(FIFO), 以支持基于套接字的启动。systemd-journald将监听以下这些套接字和路径,在文件系统中可见:
/dev/kmsg, /dev/log, /run/systemd/journal/dev-log, /run/systemd/journal/socket, /run/systemd/journal/stdout
解决方案
使用systemctl restart systemd-journald.socket
重启端口(并不是systemd-journald.service),仅此一步就可以解决问题,logger
能够成功发送消息了。
注意:没有重新启动rsyslogd。
小结
本文通过strace
来跟踪比较两个执行路径,直接获取到了关键报错,再据此线索解决问题。此外,开启rsyslog
的debug级别日志也许能看到更详细的信息,但在可能的情况下strace
更利于发现问题的真相。
在定位到/dev/log
之后问题被解决,但解决方案与socket“拒绝连接”的原因之间尚有链条缺失,由于测试环境已经销毁,无法追踪了。有其他老师提到可能是system启动的systemd-journald
与rsyslog sock
有冲突,导致rsyslog
套接字无法正常发送数据,但问题的概率特征与本文有出入。另有提及配置修改导致不记录日志的现象,将/etc/systemd/journald.conf
中的配置ForwardToSyslog,修改为yes
即可(针对的是systemd-journald.service)。
对于/dev/log
丢失的情况,论坛提到使用手动链接也可以:ln -s /run/systemd/journal/dev-log /dev/log
。