Log4j RollingFileAppender未写入mapper与reducer日志至文件问题咨询
首先得明确核心原因:Hadoop的Mapper和Reducer任务是在集群的TaskTracker(YARN模式下是NodeManager)节点上以独立JVM进程运行的,你当前的应用级Log4j配置只能管控Driver进程的日志,没法直接覆盖任务节点上子进程的日志输出。要让mapper/reducer的日志写入指定本地文件,按以下步骤调整即可:
1. 为任务进程分发自定义Log4j配置
你需要把自定义的log4j.properties文件同步到所有任务节点,让mapper/reducer进程加载这个配置。在作业提交代码中添加以下配置:
Configuration conf = new Configuration(); // 针对Hadoop 2.x/YARN版本 conf.set("mapreduce.job.log4j.properties", "log4j.properties"); // 如果是旧版Hadoop(0.20.x/1.x),替换为: // conf.set("mapred.job.log4j.properties", "log4j.properties");
同时要确保log4j.properties文件被打包进作业的JAR包,或者通过DistributedCache(旧版)/Configuration.addResource(新版)分发到节点。
2. 调整日志级别,避免遗漏关键日志
你当前配置中log4j.logger.com.ournamespace=ERROR的级别过高,会过滤掉mapper/reducer中INFO及以下的日志输出。建议调整为更合理的级别,比如INFO:
log4j.logger.com.ournamespace=INFO, APP_APPENDER, ERROR_APPENDER
3. 补全RollingFileAppender的完整配置
你的现有配置只写了部分参数,要确保两个Appender的配置完整,示例如下:
ODS.LOG.DIR=/var/log/appLogs ODS.LOG.INFO.FILE=application.log ODS.LOG.ERROR.FILE=application_error.log # Root logger选项 log4j.rootLogger=ERROR, console log4j.logger.com.ournamespace=INFO, APP_APPENDER, ERROR_APPENDER # Console Appender(可选启用) log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n # INFO级别滚动文件Appender log4j.appender.APP_APPENDER=org.apache.log4j.RollingFileAppender log4j.appender.APP_APPENDER.File=${ODS.LOG.DIR}/${ODS.LOG.INFO.FILE} log4j.appender.APP_APPENDER.MaxFileSize=10MB log4j.appender.APP_APPENDER.MaxBackupIndex=10 log4j.appender.APP_APPENDER.Threshold=INFO log4j.appender.APP_APPENDER.layout=org.apache.log4j.PatternLayout log4j.appender.APP_APPENDER.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n # ERROR级别滚动文件Appender log4j.appender.ERROR_APPENDER=org.apache.log4j.RollingFileAppender log4j.appender.ERROR_APPENDER.File=${ODS.LOG.DIR}/${ODS.LOG.ERROR.FILE} log4j.appender.ERROR_APPENDER.MaxFileSize=10MB log4j.appender.ERROR_APPENDER.MaxBackupIndex=5 log4j.appender.ERROR_APPENDER.Threshold=ERROR log4j.appender.ERROR_APPENDER.layout=org.apache.log4j.PatternLayout log4j.appender.ERROR_APPENDER.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n # 禁止日志重复输出到Root Logger log4j.additivity.com.ournamespace=false
这里的log4j.additivity.com.ournamespace=false很重要,能避免业务日志同时输出到Root Logger的控制台中。
4. 确保任务节点的日志目录权限
要保证/var/log/appLogs目录在所有任务节点上都已创建,并且运行TaskTracker/NodeManager的用户拥有该目录的读写权限,否则日志文件无法正常生成。可以提前通过集群管理脚本批量创建目录,或者在作业初始化时添加目录检查逻辑。
额外提示(YARN模式)
如果你的集群用的是YARN,默认会把任务日志聚合到HDFS上。如果需要优先保留本地日志,可以调整yarn.log-aggregation-enable=false,但上述方法依然有效——因为我们是让任务进程直接将日志写入指定本地文件。
内容的提问来源于stack exchange,提问作者Paras

