共计 3403 个字符,预计需要花费 9 分钟才能阅读完成。
导读 | 本文主要介绍了 Tomcat 中 catalina.out 和 catalina.log 的区别和用途详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 |
catalina.out 其实是 tomcat 的标准输出 (stdout) 和标准出错(stderr),这是在 tomcat 的启动脚本里指定的,如果没有修改的话 stdout 和 stderr 会重定向到这里。所以我们在应用里使用 System.out 打印的东西都会到这里来。另外,如果我们在应用里使用其他的日志框架,配置了向 Console 输出的,则也会在这里出现。比如以 logback 为例,如果配置 ch.qos.logback.core.ConsoleAppender 则会输出到 catalina.out 里。
这两个日志都是通过 logging.properties 配置的(默认情况下,启动脚本里指定了 java.util.logging.config.file 和 java.util.logging.manager 两个变量)。一个典型的 logging.properties 可能如下所示:
handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
1catalina.org.apache.juli.FileHandler.level = INFO
1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.FileHandler.prefix = catalina.
2localhost.org.apache.juli.FileHandler.level = FINE
2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
2localhost.org.apache.juli.FileHandler.prefix = localhost.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler
这个文件大致的意思是,root 输出到 catalina 和 console。而这里的 catalina 按照配置对应的是 catalina.{yyyy-MM-dd}.log,这里的 console 最终会输出到 catalina.out。这就是我们看到 catalina.{yyyy-MM-dd}.log 和 catalina.out 的日志很多都是一样的原因。
配置文件中还有一个 localhost,所有 logname 或 parent logname 为 org.apache.catalina.core.ContainerBase.[Catalina].[localhost]的都会输出到 localhost.{yyyy-MM-dd}.log 文件。而这个 logname 又代表着什么呢?在 tomcat 中有一个 server.xml 的配置文件,其中有这么一个片段:
我们可以这么简单的理解: 一个 Tomcat 进程对应着一个 Engine,一个 Engine 下可以有多个 Host(Virtual Host),一个 Host 里可以有多个 Context,比如我们常常将应用部署在 ROOT 下还是 webapps 里其他目录,这个就是 Context。
这其中 Engine 对应着 tomcat 里的 StandardEngine 类,Host 对应着 StandardHost 类,而 Context 对应着 StandardContext。这几个类都是从 ContainerBase 派生。这些类里打的一些跟应用代码相关的日志都是使用 ContainerBase 里的 getLogger,而这个这个 logger 的 logger name 就是: org.apache.catalina.core.ContainerBase.[current container name].[current container name]…
而我们一个 webapp 里 listener, filter, servlet 的初始化就是在 StandardContext 里进行的,比如 ROOT 里有一个 listener 初始化出异常了,打印日志则 logger name 是 org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/]。这其中 Catalina 和 localhost 是上面 xml 片段里的 Engine 和 Host 的 name,而 [/] 是 ROOT 对应的 StandardContext 的 name。所以 listener, filter, servlet 初始化时的日志是需要看 localhost.{yyyy-MM-dd}.log 这个日志的。比如现在我们使用 Spring,Spring 的初始化我们往往是使用 Spring 提供的一个 listener 进行的,而如果 Spring 初始化时因为某个 bean 初始化失败,导致整个应用没有启动,这个时候的异常日志是输出到 localhost 中的,而不是 cataina.out 中。所以有的时候我们应用无法启动了,然后找 catalina.out 日志,但最后也没有定位根本原因是什么,就是因为我们找的日志不对。但有的时候 catalina.out 里也有我们想要的日志,那是因为我们的应用或使用的一些组件自己捕获了异常,然后将其打印了,这个时候如果恰好这些日志被我们配置成输出到 console,则这些日志也会在 catalina.out 里出现了。
那么总结起来,catalina.out 即标准输出和标准出错,所有输出到这两个位置的都会进入 catalina.out,这里包含 tomcat 运行自己输出的日志以及应用里向 console 输出的日志。catalina.{yyyy-MM-dd}.log 是 tomcat 自己运行的一些日志,这些日志还会输出到 catalina.out,但是应用向 console 输出的日志不会输出到 catalina.{yyyy-MM-dd}.log。localhost.{yyyy-MM-dd}.log 主要是应用初始化 (listener, filter, servlet) 未处理的异常最后被 tomcat 捕获而输出的日志,而这些未处理异常最终会导致应用无法启动。
最后想想,这里分几个日志文件其实不利于问题查找,为啥不干脆都输出到 catalina.out 里呢?我想 tomcat 作为通用容器本身,可能考虑到 Engine 下有多个 Host,每个 Host 的日志还是要输出到不同的文件。而实际中我们往往是单容器,单 Host,甚至是只有一个 ROOT 的 Context。
一般是用 log4j 按照业务划分,对一些比较重要的业务会单独打到一个文件,方便容易定位问题,,其他的默认会打到 catalina。
到此这篇关于 Tomcat 中 catalina.out 和 catalina.log 的区别和用途详解的文章就介绍到这了
![post-qrcode](https://www.xgss.net/wp-content/uploads/2023/07/二维码-微信公众号256x256.jpg)