背景:在做自动化检查工具(每隔一分钟检测tomcat进程是否存在,不存在则启动)时,发现一个问题,当connector端口被占用时,进程可以正常启动,但是服务不可用。所以脚本检测到进程,就以为服务已经正常起来了,这就造成一个假象。
Tomcat version:7.0.39
Oct 23, 2015 3:13:16 AM org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
Oct 23, 2015 3:13:16 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Oct 23, 2015 3:13:16 AM org.apache.coyote.AbstractProtocol init
SEVERE: Failed to initialize end point associated with ProtocolHandler ["http-bio-8080"]
java.net.BindException: Address already in use <null>:8080
at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:406)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:610)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:429)
at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:981)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:814)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.startup.Catalina.load(Catalina.java:633)
at org.apache.catalina.startup.Catalina.load(Catalina.java:658)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
Caused by: java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
at java.net.ServerSocket.bind(ServerSocket.java:376)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:181)
at org.apache.tomcat.util.net.DefaultServerSocketFactory.createSocket(DefaultServerSocketFactory.java:49)
at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:393)
... 17 more
Oct 23, 2015 3:13:16 AM org.apache.catalina.core.StandardService initInternal
SEVERE: Failed to initialize connector [Connector[HTTP/1.1-8080]]
org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-8080]]
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:106)
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:814)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.startup.Catalina.load(Catalina.java:633)
at org.apache.catalina.startup.Catalina.load(Catalina.java:658)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:983)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
... 12 more
Caused by: java.net.BindException: Address already in use <null>:8080
at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:406)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:610)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:429)
at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:981)
... 13 more
Caused by: java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
at java.net.ServerSocket.bind(ServerSocket.java:376)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:181)
at org.apache.tomcat.util.net.DefaultServerSocketFactory.createSocket(DefaultServerSocketFactory.java:49)
at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:393)
... 17 more
Oct 23, 2015 3:13:16 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 784 ms
Oct 23, 2015 3:13:16 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Oct 23, 2015 3:13:16 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.39
Oct 23, 2015 3:13:16 AM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor /data/apache-tomcat-master/conf/Catalina/localhost/ac_ids.xml
log4j:WARN No such property [maxBackupIndex] in org.apache.log4j.DailyRollingFileAppender.
log4j:WARN No such property [maxBackupIndex] in org.apache.log4j.DailyRollingFileAppender.
Oct 23, 2015 3:13:25 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /data/apache-tomcat-master/webapps/ROOT
Oct 23, 2015 3:13:25 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 8926 ms
解决方案:
1、在启动时检测该端口是否被占用:
/usr/sbin/lsof -i:8080
netstat -lnp | grep :8080
如果是被该tomcat进程占用,则kill 掉进程即可,否则,输出错误信息,并发告警邮件。
2、在setenv.sh 中增加如下配置
CATALINA_OPTS="$CATALINA_OPTS -Dorg.apache.catalina.startup.EXIT_ON_INIT_FAILURE=true"
思路:当shutdown 端口被占用时,会停止服务,并销毁,日志如下,所以就只能看tomcat源码了。
Oct 22, 2015 10:29:15 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /data/apache-tomcat-master/webapps/ROOT
Oct 22, 2015 10:29:15 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8082"]
Oct 22, 2015 10:29:15 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 9074 ms
Oct 22, 2015 10:29:15 PM org.apache.catalina.core.StandardServer await
SEVERE: StandardServer.await: create[localhost:8005]:
java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
at java.net.ServerSocket.bind(ServerSocket.java:376)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at org.apache.catalina.core.StandardServer.await(StandardServer.java:427)
at org.apache.catalina.startup.Catalina.await(Catalina.java:766)
at org.apache.catalina.startup.Catalina.start(Catalina.java:712)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:456)
Oct 22, 2015 10:29:15 PM org.apache.coyote.AbstractProtocol pause
INFO: Pausing ProtocolHandler ["http-bio-8082"]
Oct 22, 2015 10:29:15 PM org.apache.catalina.core.StandardService stopInternal
INFO: Stopping service Catalina
Oct 22, 2015 10:29:15 PM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["http-bio-8082"]
Oct 22, 2015 10:29:15 PM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["http-bio-8082"]
部分tomcat源码
org/apache/catalina/startup/Catalina.java
getServer().setCatalina(this);
// Stream redirection
initStreams();
// Start the new server
try {
getServer().init();
} catch (LifecycleException e) {
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
throw new java.lang.Error(e);
} else {
log.error("Catalina.start", e);
}
}
long t2 = System.nanoTime();
if(log.isInfoEnabled()) {
log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
}
如果该配置为true(默认为false),则会throw异常并退出,否则程序继续往下走,和我们的出错信息是一致的。
-Dorg.apache.catalina.startup.EXIT_ON_INIT_FAILURE=true
If true, the server will exit if an exception happens during the server initialization phase.
If not specified, the default value of false will be used.
http://tomcat.apache.org/tomcat-7.0-doc/config/systemprops.html
最后问题来了,为什么该参数默认是false呢?用于什么场景呢?