无服务端配置权限时如何获取Slf4j simpleLogger历史控制台日志
问题场景
- Python编写的GUI程序通过本地HTTP与Java服务端通信,可观测到服务端实时控制台输出,示例日志:
[HTTP-Dispatcher] DEBUG src.app.Connecter - connecting to the server...
- 尝试执行
journalctl -r导出服务端日志,结果中无任何该服务相关输出。 - 已知服务端使用Slf4j打印日志,日志实例初始化代码:
private static Logger log = LoggerFactory.getLogger(SimpleServer.class);
- 约束:无服务端配置修改权限,不确定服务是否配置了文件日志落盘,仅需通过bash类工具获取服务端输出到控制台的历史Slf4j日志。
排查与解决方法
为什么journalctl查不到日志
只有被systemd托管、且标准输出/标准错误未被重定向、默认交给systemd捕获的服务,日志才会写入journald供journalctl查询。查询无结果说明该Java服务并非通过systemd unit启动,或是启动时手动重定向了输出流,日志没有进入journald的收集范围。
第一步:定位Java服务进程ID
执行以下命令过滤出所有Java进程,从启动命令里匹配到对应SimpleServer的进程,记录第二列的PID数值:
ps aux | grep java
第二步:检查进程输出流指向,确认历史日志存储位置
拿到PID后,替换命令中的<PID>为实际数值,查看进程标准输出(fd/1)、标准错误(fd/2)对应的文件路径:
ls -l /proc/<PID>/fd/1 /proc/<PID>/fd/2
- 如果输出结果中两个fd指向的是普通磁盘文件路径,直接读取该文件即可拿到所有历史控制台日志。
- 如果输出指向
/dev/pts/数字这类伪终端路径,说明服务是在某个终端会话中前台启动的,日志仅实时输出到对应终端,已经输出过、超出终端滚动缓冲区的历史日志没有任何工具可以回溯获取——系统层面没有对这部分输出做持久化存储。
无历史日志留存时的后续日志捕获方案
如果确认历史日志未持久化,可通过以下bash工具在不修改服务配置的前提下,捕获后续产生的控制台日志落盘:
- 可重启服务的场景:启动时直接重定向输出流到文件,不需要修改服务任何配置
# 替换为实际的Java服务启动命令,所有控制台输出会追加写入server.log java [你的服务启动JVM参数/主类/jar包路径] >> ./server.log 2>&1 - 不可重启服务的场景:用
strace附加到运行进程,捕获后续的控制台写操作
捕获到需要的日志后按# 附加到目标进程,捕获所有向标准输出、标准错误的写入操作,原始输出写入strace_tmp.log strace -p <PID> -s 65535 -e trace=write,writev -o ./strace_tmp.logCtrl+C终止strace即可,不会影响原Java服务正常运行。执行以下命令可以从strace的原始输出中提取出纯文本日志:grep -E 'write\(1,|write\(2,' strace_tmp.log | sed 's/.*write([12], "//;s/".*//' > ./server_captured.log
注意:使用strace附加进程需要root权限或者和目标进程相同的属主权限,附加期间会给进程带来极轻微的性能损耗,生产环境谨慎长时间运行。
内容的提问来源于stack exchange,提问作者Azii
相关产品推荐
相关产品推荐

