服务器启动后首次运行项目Log4j日志未生成及FileNotFoundException排查
这问题我之前帮不少开发者排查过,结合你给出的Log4j配置片段(能看出来是Log4j 1.x版本)和现象,大概率是下面几个原因之一:
1. 日志文件的父目录未提前创建
Log4j 1.x的FileAppender有个老问题:不会自动创建日志文件的父目录。如果你的File appender配置的路径是类似logs/app.log这种带子目录的相对路径,服务器首次启动时logs目录还不存在,Log4j尝试写入时就会抛出FileNotFoundException。
而第二次启动时,要么是第一次启动后某个流程(比如项目里的其他初始化代码、手动操作)创建了这个目录,要么是服务器重启时自动生成了必要目录,所以Log4j能正常创建日志文件了。
你可以检查log4j.properties里的log4j.appender.File.File配置项,看看是不是指定了需要父目录的路径。
2. 进程首次启动时无写入权限
服务器首次启动项目时,运行项目的系统用户可能没有目标日志目录的写入权限。比如服务器用了一个受限用户启动,首次运行时该用户还没被授予日志目录的读写权限,导致无法创建文件;而第二次启动前,可能管理员手动调整了权限,或者某些初始化脚本自动配置了权限,所以就能正常写入了。
3. 目录创建逻辑晚于Log4j初始化
如果你的项目里有自己的代码负责创建日志目录,但这段代码的执行时机晚于Log4j的初始化时机,就会出现这个问题:第一次启动时Log4j先尝试创建文件,但目录还没被创建,抛出异常;第二次启动时,目录已经在第一次启动的后续流程中被创建了,所以Log4j能正常工作。
比如,项目的初始化Bean在Log4j完成配置之后才执行创建目录的操作,第一次启动顺序不对,第二次就没问题了。
4. Log4j 1.x的初始化缓存问题
极少数情况下,Log4j 1.x首次初始化时会因为类加载顺序问题,导致文件路径解析异常,抛出找不到文件的错误;第二次启动时,类加载缓存已经存在,路径解析正常,就能创建文件了。不过这个情况比较少见,优先级低于前面几个原因。
- 先查路径:打开你的
log4j.properties,找到log4j.appender.File.File的配置,手动检查目标路径的父目录是否存在,不存在的话手动创建后再启动试试。 - 权限排查:确认运行项目的服务器用户对目标目录有读写权限,必要时用
chmod或系统权限管理工具调整。 - 调整初始化顺序:把创建日志目录的代码移到Log4j初始化之前执行(比如放在项目启动的最前置钩子里)。
- 升级Log4j版本:考虑升级到Log4j 2.x,它不仅修复了自动创建父目录的问题,还在性能和安全性上有很大提升。
内容的提问来源于stack exchange,提问作者RAP

