当我们在Linux下启动tomcat的时候,通过ps查看其进程信息为,接下来的内容我们就以此进行分析:

[tomcat@fdd ~]$ ps -ef |grep java
tomcat : tty1 :: /usr/bin/java -Djava.util.logging.config.file=/home/tomcat/apache-tomcat-7.0./conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize= -Djava.endorsed.dirs=/home/tomcat/apache-tomcat-7.0./endorsed -classpath /home/tomcat/apache-tomcat-7.0./bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0./bin/tomcat-juli.jar -Dcatalina.base=/home/tomcat/apache-tomcat-7.0. -Dcatalina.home=/home/tomcat/apache-tomcat-7.0. -Djava.io.tmpdir=/home/tomcat/apache-tomcat-7.0./temp org.apache.catalina.startup.Bootstrap start

1 startup.sh分析

我们启动Tomcat的时候,执行的是sh startup.sh,那么在startup.sh中做了哪些事情呢,实际上就是调用catalina.sh,具体过程请看下面分析

……
# 指定Tomcat路径
PRGDIR=`dirname "$PRG"`
# 指定调用脚本
EXECUTABLE=catalina.sh
……
# 执行启动脚本
exec "$PRGDIR"/"$EXECUTABLE" start "$@"

2. catalina.sh分析

在catalina.sh中完成环境检查、环境初始化、参数初始化、启动操作,也就是在这个里面利用JVM中的java命令执行tomcat的main方法的:

……
# 环境检查
case $CATALINA_HOME in
*:*) echo "Using CATALINA_HOME: $CATALINA_HOME";
echo "Unable to start as CATALINA_HOME contains a colon (:) character";
exit ;
esac
case $CATALINA_BASE in
*:*) echo "Using CATALINA_BASE: $CATALINA_BASE";
echo "Unable to start as CATALINA_BASE contains a colon (:) character";
exit ;
esac
……
# 初始化环境信息、参数初始化
if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
. "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
. "$CATALINA_HOME/bin/setenv.sh"
fi
……
# 启动Tomcat,支持
if [ "$1" = "-security" ] ; then
if [ $have_tty -eq ]; then
echo "Using Security Manager"
fi
shift
eval "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
-Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
>> "$CATALINA_OUT" >& "&" else
eval "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
>> "$CATALINA_OUT" >& "&" fi
……

3 Bootstrap分析

通过第二章节,我们可以看出实际上调用的是 java org.apache.catalina.startup.Bootstrap这个类,那么我们就来分析一下这个类

3.1 静态代码

类中的静态代码块完成一些参数初始化:

static {
// Will always be non-null
String userDir = System.getProperty("user.dir"); // Home first
String home = System.getProperty(Globals.CATALINA_HOME_PROP);
File homeFile = null; if (home != null) {
File f = new File(home);
try {
homeFile = f.getCanonicalFile();
} catch (IOException ioe) {
homeFile = f.getAbsoluteFile();
}
} if (homeFile == null) {
// First fall-back. See if current directory is a bin directory
// in a normal Tomcat install
File bootstrapJar = new File(userDir, "bootstrap.jar"); if (bootstrapJar.exists()) {
File f = new File(userDir, "..");
try {
homeFile = f.getCanonicalFile();
} catch (IOException ioe) {
homeFile = f.getAbsoluteFile();
}
}
} if (homeFile == null) {
// Second fall-back. Use current directory
File f = new File(userDir);
try {
homeFile = f.getCanonicalFile();
} catch (IOException ioe) {
homeFile = f.getAbsoluteFile();
}
} catalinaHomeFile = homeFile;
System.setProperty(
Globals.CATALINA_HOME_PROP, catalinaHomeFile.getPath()); // Then base
String base = System.getProperty(Globals.CATALINA_BASE_PROP);
if (base == null) {
catalinaBaseFile = catalinaHomeFile;
} else {
File baseFile = new File(base);
try {
baseFile = baseFile.getCanonicalFile();
} catch (IOException ioe) {
baseFile = baseFile.getAbsoluteFile();
}
catalinaBaseFile = baseFile;
}
System.setProperty(
Globals.CATALINA_BASE_PROP, catalinaBaseFile.getPath());
}

3.2 调用main方法

main方法是启动一个java程序的入口,任何程序都会有自己的main方法,tomcat是一个WEB容器,也不例外:

public static void main(String args[]) {
//如果守护进程为空,则进行初始化
if (daemon == null) {
// Don't set daemon until init() has completed
Bootstrap bootstrap = new Bootstrap();
try {
//初始化守护进程,初始化内容参考3.2.1
bootstrap.init();
} catch (Throwable t) {
handleThrowable(t);
t.printStackTrace();
return;
}
daemon = bootstrap;
} else {
// When running as a service the call to stop will be on a new
// thread so make sure the correct class loader is used to prevent
// a range of class not found exceptions.
Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
} try {
//判断执行命令,并进行相应操作
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
} if (command.equals("startd")) {
args[args.length - 1] = "start";
//加载启动参数,参考3.2.2
daemon.load(args);
//启动Tomcat,参考3.2.3
daemon.start();
} else if (command.equals("stopd")) {
args[args.length - 1] = "stop";
//停止Tomcat守护进程,参考3.2.4
daemon.stop();
} else if (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args);
daemon.start();
} else if (command.equals("stop")) {
//单独停止Tomcat服务器,参考3.2.5
daemon.stopServer(args);
} else if (command.equals("configtest")) {
//测试配置
daemon.load(args);
if (null==daemon.getServer()) {
System.exit(1);
}
System.exit(0);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable t) {
// Unwrap the Exception for clearer error reporting
if (t instanceof InvocationTargetException &&
t.getCause() != null) {
t = t.getCause();
}
handleThrowable(t);
t.printStackTrace();
System.exit(1);
} }

3.2.1 初始化守护进程

此部分完成类加载器初始化

public void init() throws Exception {
//初始化类加载器,根据catalina.properties中的加载项进行类加载
initClassLoaders(); Thread.currentThread().setContextClassLoader(catalinaLoader); SecurityClassLoad.securityClassLoad(catalinaLoader); // Load our startup class and call its process() method
if (log.isDebugEnabled())
log.debug("Loading startup class");
Class<?> startupClass =
catalinaLoader.loadClass
("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance(); // Set the shared extensions class loader
if (log.isDebugEnabled())
log.debug("Setting startup class properties");
String methodName = "setParentClassLoader";
Class<?> paramTypes[] = new Class[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;
Method method =
startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues); catalinaDaemon = startupInstance; }

3.3.2 加载启动参数

在启动脚本中,增加了各种启动参数,此部分就完成这些参数的利用。

//实际调用org.apache.catalina.startup.Catalina类中的load方法
private void load(String[] arguments)
throws Exception { // Call the load() method
String methodName = "load";
Object param[];
Class<?> paramTypes[];
if (arguments==null || arguments.length==0) {
paramTypes = null;
param = null;
} else {
paramTypes = new Class[1];
paramTypes[0] = arguments.getClass();
param = new Object[1];
param[0] = arguments;
}
Method method =
catalinaDaemon.getClass().getMethod(methodName, paramTypes);
if (log.isDebugEnabled())
log.debug("Calling startup class " + method);
//反射调用
method.invoke(catalinaDaemon, param); }

接下来,我们看具体的load

//org.apache.catalina.startup.Catalina.load(String[] args)
public void load(String args[]) { try {
//参数检查
if (arguments(args)) {
//加载参数
load();
}
} catch (Exception e) {
e.printStackTrace(System.out);
}
} //org.apache.catalina.startup.Catalina.load()
public void load() { long t1 = System.nanoTime();
//检查临时目录
initDirs(); // Before digester - it may be needed
initNaming(); // Create and execute our Digester
// 初始化XML解析器,参考:http://blog.csdn.net/u011545486/article/details/52005412
Digester digester = createStartDigester(); InputSource inputSource = null;
InputStream inputStream = null;
File file = null;
try {
try {
//获取server.xml配置文件
file = configFile(); //通过new File()方式读取文件
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("catalina.configFail", file), e);
}
}
if (inputStream == null) { //读取失败,则通过getResource方式读取文件
try {
inputStream = getClass().getClassLoader()
.getResourceAsStream(getConfigFile());
inputSource = new InputSource
(getClass().getClassLoader()
.getResource(getConfigFile()).toString());
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("catalina.configFail",
getConfigFile()), e);
}
}
} // This should be included in catalina.jar
// Alternative: don't bother with xml, just create it manually.
if (inputStream == null) { //如果没有server.xml配置文件,则采用jar包中自带的server-embed.xml
try {
inputStream = getClass().getClassLoader()
.getResourceAsStream("server-embed.xml");
inputSource = new InputSource
(getClass().getClassLoader()
.getResource("server-embed.xml").toString());
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("catalina.configFail",
"server-embed.xml"), e);
}
}
} if (inputStream == null || inputSource == null) { //仍不存在,则进行警告处理,并结束启动
if (file == null) {
log.warn(sm.getString("catalina.configFail",
getConfigFile() + "] or [server-embed.xml]"));
} else {
log.warn(sm.getString("catalina.configFail",
file.getAbsolutePath()));
if (file.exists() && !file.canRead()) {
log.warn("Permissions incorrect, read permission is not allowed on the file.");
}
}
return;
} try {
//解析XML配置
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);
} catch (SAXParseException spe) {
log.warn("Catalina.start using " + getConfigFile() + ": " +
spe.getMessage());
return;
} catch (Exception e) {
log.warn("Catalina.start using " + getConfigFile() + ": " , e);
return;
}
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// Ignore
}
}
}
//设置catalina属性
getServer().setCatalina(this);
getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile()); // Stream redirection
// 设置日志输出流
initStreams(); // Start the new server
try {
//实际调用的是: org.apache.catalina.util.LifecycleBase.init()
//启动Tomcat
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");
}
}

3.2.3 启动Server

完成参数服务初始化之后,就可以进行Server启动。主要包含两部分:Service启动和Server启动。启动过程具体处理在org.apache.catalina.util.LifecycleBase.start()中完成,然后调用org.apache.catalina.core.StandardServer.startInternal()方法进行具体的启动操作

protected void startInternal() throws LifecycleException {

        fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING); globalNamingResources.start(); // Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) { //启动Service
services[i].start();
}
}
}

3.2.4 停止Tomcat守护进程

此实现过程在org.apache.catalina.startup.Catalina.stop()实现。

public void stop() {

        try {
// Remove the ShutdownHook first so that server.stop()
// doesn't get invoked twice
if (useShutdownHook) {
Runtime.getRuntime().removeShutdownHook(shutdownHook); // If JULI is being used, re-enable JULI's shutdown to ensure
// log messages are not lost
LogManager logManager = LogManager.getLogManager();
if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook(
true);
}
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// This will fail on JDK 1.2. Ignoring, as Tomcat can run
// fine without the shutdown hook.
} // Shut down the server
try {
//获取服务
Server s = getServer();
LifecycleState state = s.getState();
if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
&& LifecycleState.DESTROYED.compareTo(state) >= 0) {
// Nothing to do. stop() was already called
} else {
//停止服务
s.stop();
s.destroy();
}
} catch (LifecycleException e) {
log.error("Catalina.stop", e);
} }

3.2.5 单独停止Tomcat服务

此实现在org.apache.catalina.startup.Catalina.stopServer(String[] arguments)

public void stopServer(String[] arguments) {

        if (arguments != null) {
arguments(arguments);
}
//获取Server
Server s = getServer();
if (s == null) {
// Create and execute our Digester
Digester digester = createStopDigester();
File file = configFile();
//如果不存在,则通过配置文件获取Server信息
try (FileInputStream fis = new FileInputStream(file)) {
InputSource is =
new InputSource(file.toURI().toURL().toString());
is.setByteStream(fis);
digester.push(this);
digester.parse(is);
} catch (Exception e) {
log.error("Catalina.stop: ", e);
System.exit(1);
}
} else {
// Server object already present. Must be running as a service
try {
//停止服务
s.stop();
} catch (LifecycleException e) {
log.error("Catalina.stop: ", e);
}
return;
} // Stop the existing server
s = getServer();
if (s.getPort()>0) {
//通过SOCKET通讯发起停止指令
try (Socket socket = new Socket(s.getAddress(), s.getPort());
OutputStream stream = socket.getOutputStream()) {
String shutdown = s.getShutdown();
for (int i = 0; i < shutdown.length(); i++) {
stream.write(shutdown.charAt(i));
}
stream.flush();
} catch (ConnectException ce) {
log.error(sm.getString("catalina.stopServer.connectException",
s.getAddress(),
String.valueOf(s.getPort())));
log.error("Catalina.stop: ", ce);
System.exit(1);
} catch (IOException e) {
log.error("Catalina.stop: ", e);
System.exit(1);
}
} else {
log.error(sm.getString("catalina.stopServer"));
System.exit(1);
}
}

通过对比发现,stop()方法与stopServer()方法的区别在于,stop()在执行停止的后,同时进行destroy()操作,而stopServer()并没有发起destory操作。

同时我们可以通过Socket通讯进行关闭Tomcat,在Server.xml中配置了<Server port="8005" shutdown="SHUTDOWN">,那么Tomcat就会开启8005端口,我们可以执行

telnet x.x.x.x 8005

输入: SHUTDOWN

就会发现Tomcat停止了。

那么爱思考的小伙伴就会考虑了,这样岂不是很不安全,如果别人恶意访问我的8005端口,然后发送SHUTDOWN,那我的Tomcat岂不是就给停掉了,这样风险太大了。

放心吧,Tomcat监听的8005端口是监听127.0.0.1的8005端口而不是所有IP的8005端口,除了本机可以访问,其他电脑是不可访问的。

#查看8005端口
C:\Users\FDD>netstat -an|findstr
TCP 127.0.0.1: 0.0.0.0: LISTENING #查看8080端口
C:\Users\FDD>netstat -an|findstr
TCP 0.0.0.0: 0.0.0.0: LISTENING
TCP 192.168.0.115: 58.251.100.102: ESTABLISHED #通过对比可发现,8005是挂在127.0.0.1的,而8080是挂在0.0.0.(表示本机的所有IP)的

附录:

一、Catalina生命周期

Common interface for component life cycle methods. Catalina components may implement this interface (as well as the appropriate interface(s) for the functionality they support) in order to provide a consistent mechanism to start and stop the component.
The valid state transitions for components that support Lifecycle are:

            start()
-----------------------------
| |
| init() |
NEW -»-- INITIALIZING |
| | | | ------------------«-----------------------
| | |auto | | |
| | \|/ start() \|/ \|/ auto auto stop() |
| | INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»--- |
| | | | |
| |destroy()| | |
| --»-----«-- ------------------------«-------------------------------- ^
| | | |
| | \|/ auto auto start() |
| | STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
| \|/ ^ | ^
| | stop() | | |
| | -------------------------- | |
| | | | |
| | | destroy() destroy() | |
| | FAILED ----»------ DESTROYING ---«----------------- |
| | ^ | |
| | destroy() | |auto |
| --------»----------------- \|/ |
| DESTROYED |
| |
| stop() |
----»-----------------------------»------------------------------ Any state can transition to FAILED. Calling start() while a component is in states STARTING_PREP, STARTING or
STARTED has no effect. Calling start() while a component is in state NEW will cause init() to be
called immediately after the start() method is entered. Calling stop() while a component is in states STOPPING_PREP, STOPPING or
STOPPED has no effect. Calling stop() while a component is in state NEW transitions the component
to STOPPED. This is typically encountered when a component fails to start and
does not start all its sub-components. When the component is stopped, it will
try to stop all sub-components - even those it didn't start.

二、Tomcat 启动日志

Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server version:        Apache Tomcat/7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server built:          Apr 11 2016 07:57:09 UTC
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server number:         7.0.69.0
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: OS Name:               Linux
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: OS Version:            2.6.32-642.11.1.el6.x86_64
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Architecture:          amd64
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Java Home:             /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.121.x86_64/jre
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: JVM Version:           1.7.0_121-mockbuild_2016_11_11_19_18-b00
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: JVM Vendor:            Oracle Corporation
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: CATALINA_BASE:         /home/tomcat/apache-tomcat-7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: CATALINA_HOME:         /home/tomcat/apache-tomcat-7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.util.logging.config.file=/home/tomcat/apache-tomcat-7.0.69/conf/logging.properties
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.endorsed.dirs=/home/tomcat/apache-tomcat-7.0.69/endorsed
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcatalina.base=/home/tomcat/apache-tomcat-7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcatalina.home=/home/tomcat/apache-tomcat-7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.io.tmpdir=/home/tomcat/apache-tomcat-7.0.69/temp
Jan 26, 2016 11:20:31 PM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
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
Jan 26, 2016 11:20:31 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Jan 26, 2016 11:20:31 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 8801 ms

至此Catalina服务已经初始化完毕,接下来就是启动Service、Server

Jan 26, 2016 11:20:31 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Jan 26, 2016 11:20:31 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/host-manager
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/host-manager has finished in 3,197 ms
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/manager
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/manager has finished in 223 ms
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/ROOT
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/ROOT has finished in 103 ms
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/docs
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/docs has finished in 204 ms
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/examples
Jan 26, 2016 11:20:37 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/examples has finished in 1,425 ms
Jan 26, 2016 11:20:37 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Jan 26, 2016 11:20:37 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Jan 26, 2016 11:20:37 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 5455 ms

参考资料:

[1] Tomcat启动过程分析(上)

[2] Tomcat启动过程分析(下)

[3]http://www.cnblogs.com/jiaan-geng/category/741736.html

[4]http://blog.csdn.net/beliefer/article/details/51035923

Tomcat启动分析(一)-从脚本到main函数分析的更多相关文章

  1. Go Revel - main函数分析

    运行revel命令时,首先会编译整个项目,在编译时,会根据`app.conf`配置文件生成两个源码文件`tmp/main.go`.`routes/routes.go`,其中`main.go`是整个项目 ...

  2. RT-thread main函数分析

    RT-thread系统的main函数位于startup.c文件中. /** * This function will startup RT-Thread RTOS. */ void rtthread_ ...

  3. Linux-0.11内核源代码分析系列:内存管理get_free_page()函数分析

    Linux-0.11内存管理模块是源码中比較难以理解的部分,如今把笔者个人的理解发表 先发Linux-0.11内核内存管理get_free_page()函数分析 有时间再写其它函数或者文件的:) /* ...

  4. linux下写tomcat启动,重启的脚本

    启动: #bash/bin cd /finance/ LANG="en_US.UTF-8" export LANG /finance/tomcat8-finance/bin/cat ...

  5. tomcat启动控制台报Exception in thread ''main".......“Could not find the main class:.....Bootstrap”问题

    startup.bat文件打开最后end下一行加pause调试,重新启动tomcat,发现配置没问题,但是依然报错,发现是jdk版本问题,jdk1.6无法与tomcat8适配,重新装个1.7版本的jd ...

  6. 插值和空间分析(二)_变异函数分析(R语言)

    方法1.散点图 hscat(log(zinc)~, meuse, (:)*) 方法2.变异函数云图 library(gstat) cld <- variogram(log(zinc) ~ , m ...

  7. linux中tomcat启动脚本:关闭、发布、重启、测试是否成功

    说明 在使用jenkins持续集成时,需要实现自动发布包到tomcat.该脚本实现了在jenkins将包发送到linux服务器上后的自动关闭.发布.启动.测试启动是否成功的过程 思路 该思路以tomc ...

  8. Tomcat启动过程源码解读

    根据Tomcat源码来看一下Tomcat启动过程都做了什么 部分代码为主要流程代码,删去了try-catch以及一些校验逻辑,方便理解主流程 先来一张启动过程时序图,了解一下启动顺序 Tomcat启动 ...

  9. SequoiaDB 系列之五 :源码分析之main函数

    好久好久没有写博客了,因为一直要做各种事,工作上的,生活上的,这一下就是半年. 时光如梭. 这两天回头看了看写的博客,感觉都是贻笑大方. 但是还是想坚持把SequoiaDB系列写完. 初步的打算已经确 ...

随机推荐

  1. Add a Simple Action添加简单按钮

    In this lesson, you will learn how to create a Simple Action. For this purpose, a new View Controlle ...

  2. vue之虚拟DOM、diff算法

    一.真实DOM和其解析流程? 浏览器渲染引擎工作流程都差不多,大致分为5步,创建DOM树——创建StyleRules——创建Render树——布局Layout——绘制Painting 第一步,用HTM ...

  3. 【Gradle】Gradle插件

    Gradle插件 插件的作用 把插件应用到项目中,插件会扩展项目的功能,帮助在项目构建过程中做很多事情. 1.可以添加任务到项目中,帮助完成测试.编译.打包等. 2.可以添加依赖配置到项目中,可以通过 ...

  4. lambada 表达式

    1.lambada的存在来由 匿名类的一个问题是,如果匿名类的实现非常简单,例如只包含一个方法的接口,那么匿名类的语法可能看起来不实用且不清楚.在这些情况下,您通常会尝试将功能作为参数传递给另一个方法 ...

  5. acwing 49. 二叉搜索树与双向链表

    地址:https://www.acwing.com/problem/content/87/ 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表. 要求不能创建任何新的结点,只能调整树中结点指针 ...

  6. acwing 902. 最短编辑距离

    地址 https://www.acwing.com/problem/content/904/ 给定两个字符串A和B,现在要将A经过若干操作变为B,可进行的操作有: 删除–将字符串A中的某个字符删除. ...

  7. JMeter基础知识系列三

    JMeter测试结果字段的意义: Label:定义HTTP请求名称. Samples:表示这次测试中一共发出了多少个请求. Average:平均响应时长,当使用了Transaction Control ...

  8. DRF--重写views

    前戏 在前面几篇文章里,我们写了get请求,post请求,put请求,在来写个delete请求,大概如下. class BookView(APIView): # 查询所有的数据和post方法 def ...

  9. Django中的跨域请求问题

    本文目录 一 同源策略 二 CORS(跨域资源共享)简介 三 CORS基本流程 四 CORS两种请求详解 五 Django项目中支持CORS 回到目录 一 同源策略 同源策略(Same origin ...

  10. SVN基本使用

    1.把服务器的所有内容下载到本地 svn checkout 服务器地址 --username=使用者 --password=密码 2.添加文件 touch main.m(文件名) : 创建main.m ...