Win 또는 Linux 시스템에 배포해야하는 Java 웹 응용 프로그램이 있습니다. 이제 로깅을 위해 log4j를 추가하고 모든 배포에서 파일 경로를 변경하고 싶지 않기 때문에 로그 파일의 상대 경로를 사용하고 싶습니다. 컨테이너는 Tomcat 일 가능성이 높지만 반드시 그런 것은 아닙니다.
이를 수행하는 가장 좋은 방법은 무엇입니까?
Win 또는 Linux 시스템에 배포해야하는 Java 웹 응용 프로그램이 있습니다. 이제 로깅을 위해 log4j를 추가하고 모든 배포에서 파일 경로를 변경하고 싶지 않기 때문에 로그 파일의 상대 경로를 사용하고 싶습니다. 컨테이너는 Tomcat 일 가능성이 높지만 반드시 그런 것은 아닙니다.
이를 수행하는 가장 좋은 방법은 무엇입니까?
답변:
Tomcat은 catalina.home 시스템 속성을 설정합니다. log4j 속성 파일에서 이것을 사용할 수 있습니다. 이 같은:
log4j.rootCategory=DEBUG,errorfile
log4j.appender.errorfile.File=${catalina.home}/logs/LogFilename.log
Debian (Ubuntu 포함)에서는 ${catalina.home}
/ var / log / tomcat6에 대한 링크가없는 / usr / share / tomcat6을 가리 키므로 작동하지 않습니다. 여기에서 ${catalina.base}
.
다른 컨테이너를 사용하는 경우 유사한 시스템 속성을 찾거나 직접 정의하십시오. 시스템 속성 설정은 플랫폼 및 컨테이너에 따라 다릅니다. 그러나 Linux / Unix의 Tomcat의 경우 CATALINA_HOME / bin 디렉토리에 setenv.sh를 만듭니다. 다음이 포함됩니다.
export JAVA_OPTS="-Dcustom.logging.root=/var/log/webapps"
그러면 log4j.properties는 다음과 같습니다.
log4j.rootCategory=DEBUG,errorfile
log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log
마침내 이런 식으로 해냈습니다.
다음을 수행하는 ServletContextListener를 추가했습니다.
public void contextInitialized(ServletContextEvent event) {
ServletContext context = event.getServletContext();
System.setProperty("rootPath", context.getRealPath("/"));
}
그런 다음 log4j.properties 파일에서 :
log4j.appender.file.File=${rootPath}WEB-INF/logs/MyLog.log
이렇게하면 "rootPath"시스템 속성이 설정되기 전에 사용하지 않는 한 Log4j는 올바른 폴더에 기록합니다. 즉, ServletContextListener 자체에서는 사용할 수 없지만 앱의 다른 곳에서는 사용할 수 있어야합니다.
컨테이너 별 시스템 속성에 의존하지 않고 OS 별 경로 문제의 영향을받지 않으므로 모든 웹 컨테이너 및 OS에서 작동해야합니다. Tomcat 및 Orion 웹 컨테이너와 Windows 및 Linux에서 테스트되었으며 지금까지 잘 작동합니다.
어떻게 생각해?
Spring을 사용하면 다음을 수행 할 수 있습니다.
1) "/WEB-INF/classes/log4j-myapp.properties"와 같은 log4j 구성 파일을 만듭니다. 이름을 "log4j.properties"로 지정하지 마십시오.
예:
log4j.rootLogger=ERROR, stdout, rollingFile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.File=${myWebapp-instance-root}/WEB-INF/logs/application.log
log4j.appender.rollingFile.MaxFileSize=512KB
log4j.appender.rollingFile.MaxBackupIndex=10
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.rollingFile.Encoding=UTF-8
나중에 (3)에서 "myWebapp-instance-root"를 정의 할 것입니다.
2) web.xml에서 구성 위치를 지정하십시오.
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j-myapp.properties</param-value>
</context-param>
3) 웹앱의 루트에 고유 한 변수 이름을 지정 하십시오. 예 : "myWebapp-instance-root"
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>myWebapp-instance-root</param-value>
</context-param>
4) Log4jConfigListener 추가 :
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
다른 이름을 선택하는 경우 log4j-myapp.properties에서도 변경해야합니다.
내 기사를 참조하십시오 (이탈리아어 만 ...하지만 이해할 수 있어야 함) : http://www.megadix.it/content/configurare-path-relativi-log4j-utilizzando-spring
업데이트 (2009/08/01) 내 기사를 영어로 번역했습니다 : http://www.megadix.it/node/136
FileAppender의 경로 속성에 루트 디렉터리를 지정하지 않으면 log4j가 응용 프로그램 루트 디렉터리를 사용하지 않습니까? 따라서 다음을 사용할 수 있어야합니다.
log4j.appender.file.File = logs / MyLog.log
Java 웹 개발을 한 지 오래되었지만 가장 직관적 인 것 같고 $ {catalina.home} / logs 디렉토리에 쓰는 다른 이름의 로그와 충돌하지 않습니다.
https://stackoverflow.com/a/218037/2279200 에 대한 추가 의견으로 , 웹 앱이 다른 ServletContextListener를 암시 적으로 시작하여 이전에 호출 될 수 있고 이미 log4j를 사용하려고 시도하는 경우 중단 될 수 있습니다. log4j 구성은 로그 루트 디렉토리를 결정하는 속성이 설정되기 전에 이미 읽고 구문 분석됩니다 => 로그 파일은 현재 디렉토리 (톰캣을 시작할 때 현재 디렉토리) 아래 어딘가에 나타납니다.
이 문제에 대한 해결책은 다음과 같을뿐입니다.-log4j.properties (또는 logj4.xml) 파일의 이름을 log4j가 자동으로 읽지 않는 이름으로 바꿉니다. -컨텍스트 필터에서 속성을 설정 한 후 DOM / PropertyConfigurator 도우미 클래스를 호출하여 log4j-. {xml, properties}를 읽었는지 확인합니다.-log4j 구성 재설정 (IIRC에는이를 수행하는 방법이 있습니다)
이것은 약간의 무자비한 힘이지만, 그것이 방수로 만드는 유일한 방법입니다.
Maven을 사용하는 경우 훌륭한 솔루션이 있습니다.
다음 행을 포함하도록 pom.xml 파일을 편집하십시오.
<profiles>
<profile>
<id>linux</id>
<activation>
<os>
<family>unix</family>
</os>
</activation>
<properties>
<logDirectory>/var/log/tomcat6</logDirectory>
</properties>
</profile>
<profile>
<id>windows</id>
<activation>
<os>
<family>windows</family>
</os>
</activation>
<properties>
<logDirectory>${catalina.home}/logs</logDirectory>
</properties>
</profile>
</profiles>
여기서 logDirectory
OS 제품군에 대한 속성을 특별히 정의 합니다.
파일에 이미 정의 된 logDirectory
속성 사용 log4j.properties
:
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=${logDirectory}/mylog.log
log4j.appender.FILE.MaxFileSize=30MB
log4j.appender.FILE.MaxBackupIndex=10
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{ISO8601} [%x] %-5p [%t] [%c{1}] %m%n
추신 : 나는 이것이 Ant를 사용하여 달성 될 수 있다고 확신하지만 불행히도 그것에 대한 충분한 경험이 없습니다.
내 제안은 로그 파일이 항상 웹앱의 루트 컨텍스트 위에 기록되어야한다는 것입니다. 따라서 웹앱을 재배포하는 경우 기존 로그 파일을 재정의하고 싶지 않습니다.
내 솔루션 이케르 네즈의 유사합니다 솔루션 , 대신에 사용하는 System.setProperty(...)
I 사용을 org.apache.log4j.PropertyConfigurator.configure(Properties)
. 이를 위해 자체 구성을 찾을 수 없도록 log4j가 필요하며 수동으로로드합니다 (둘 다 Wolfgang Liebich의 답변에 설명되어 있음 ).
부두와 톰캣, 독립형 또는 IDE에서 실행,이 작품은, 제로 구성이 필요없이, 자신의 폴더에 각 응용 프로그램의 로그를 넣지 수 있습니다 방법 용기 내부에 많은 애플 리케이션 (인 문제 와 System
기반 솔루션). 이런 식으로 웹 앱 내부 어디에나 log4j 구성 파일을 넣을 수 있습니다 (예 : 하나의 프로젝트에서 모든 구성 파일이 내부에 있음 WEB-INF/
).
세부:
log4j-no-autoload.properties
클래스 경로 의 파일에 속성이 있습니다 (예 : Maven 프로젝트에서는 원래 src/main/resources
,에 패키지 됨 WEB-INF/classes
).다음과 같이 구성된 파일 어 펜더가 있습니다.
log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender
log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log
...
그리고 다음과 같은 컨텍스트 리스너가 있습니다 (Java 7의 "try-with-resource"구문으로 훨씬 짧아짐).
@WebListener
public class ContextListener implements ServletContextListener {
@Override
public void contextInitialized(final ServletContextEvent event) {
Properties props = new Properties();
InputStream strm =
ContextListener.class.getClassLoader()
.getResourceAsStream("log4j-no-autoload.properties");
try {
props.load(strm);
} catch (IOException propsLoadIOE) {
throw new Error("can't load logging config file", propsLoadIOE);
} finally {
try {
strm.close();
} catch (IOException configCloseIOE) {
throw new Error("error closing logging config file", configCloseIOE);
}
}
props.put("webAppRoot", event.getServletContext().getRealPath("/"));
PropertyConfigurator.configure(props);
// from now on, I can use LoggerFactory.getLogger(...)
}
...
}