我使用Maven构建了一个Java应用程序。它使用Maven Shade插件打包为可执行jar。此应用程序可以执行多项操作 - 其中一项是将数据上载到Hadoop集群。我使用以下命令执行程序:
$ hadoop jar <app_name>.jar <app_arg1> <app_arg2> ...
我的应用程序使用SLF4J和Log4J绑定进行日志记录 - ,Hadoop 也是如此。
使用hadoop jar
命令时,Hadoop自己的Log4J配置文件会覆盖我的应用程序的Log4J配置文件。
如何阻止我的应用程序的Log4J配置文件被覆盖?
注意:
hadoop-core:1.2.1
,slf4j-api:1.7.12
和slf4j-log4j12:1.7.12
。hadoop jar
命令,而不是java -jar
。与Hadoop集群交互的应用程序代码仅在使用hadoop jar
命令时才有效。我在a previous SO question。编辑1:(2015年2月10日)
我做了一些事情。
首先,我更改了Log4J配置文件的名称,以避免名称与Hadoop使用的默认log4j.properties
文件冲突:
log4j-<app_name>.properties
其次,我设置了HADOOP_OPTS
环境变量来告诉Log4J配置文件的名称是什么:
HADOOP_OPTS=-Dlog4j.configurationi=log4j-<app_name>.properties
第三,我设置了HADOOP_CLASSPATH
环境变量,以确保hadoop jar
命令可以获取打包在uber jar中的配置文件:
HADOOP_CLASSPATH=/absolute/path/to/<app_name>.jar
通过这些更改,我的应用程序现在可以按预期使用它自己的Log4J配置文件。感觉像黑客(因为我更喜欢使用java -jar
命令),但它解决了我的问题。
答案 0 :(得分:0)
默认情况下,Hadoop框架jar出现在classpath
中用户的jar之前。您可以使用命令中的 -Dmapreduce.job.user.classpath.first=true
参数设置(用户)jar的首选项。新命令如下所示。
hadoop jar <app_name>.jar -Dmapreduce.job.user.classpath.first=true <<app_arg1>> <<app_arg2>> ...
或者您可以将以下配置放在mapred-site.xml
中,以便始终优先考虑用户classpath
。
<property>
<name>mapreduce.job.user.classpath.first</name>
<value>true</value>
</property>
您可以在作业配置中以编程方式设置此项。
job.getConfiguration().set("mapreduce.job.user.classpath.first", "true");
你可以通过任何方式设置它,它永远不会迟到。