? 在上一次 查看tomcat啟動文件都干點啥 一文中,我們總結出, startup.bat文件的作用就是找到catalina.bat文件,然后把參數傳遞給它,在startup.bat中,調用catalina.bat的命令 call "%EXECUTABLE%" start %CMD_LINE_ARGS%,其中"%EXECUTABLE%"這個就是catalina.bat文件,這個命令至少向catalina.bat傳遞一個參數--start.
? ? ? 接下來看一下catalina.bat中的內容,內容很長:
1
@echo
off
2
rem
Licensed to the Apache Software Foundation (ASF) under one or more
3
rem
contributor license agreements. See the NOTICE file distributed with
4
rem
this work for additional information regarding copyright ownership.
5
rem
The ASF licenses this file to You under the Apache License, Version 2.0
6
rem
(the "License"); you may not use this file except in compliance with
7
rem
the License. You may obtain a copy of the License at
8
rem
9
rem
http://www.apache.org/licenses/LICENSE-2.0
10
rem
11
rem
Unless required by applicable law or agreed to in writing, software
12
rem
distributed under the License is distributed on an "AS IS" BASIS,
13
rem
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
rem
See the License for the specific language governing permissions and
15
rem
limitations under the License.
16
17
if
"%OS%" == "Windows_NT"
setlocal
18
rem
---------------------------------------------------------------------------
19
rem
Start/Stop Script for the CATALINA Server
20
rem
21
rem
Environment Variable Prerequisites
22
rem
23
rem
CATALINA_HOME May point at your Catalina "build" directory.
24
rem
25
rem
CATALINA_BASE (Optional) Base directory for resolving dynamic portions
26
rem
of a Catalina installation. If not present, resolves to
27
rem
the same directory that CATALINA_HOME points to.
28
rem
29
rem
CATALINA_OPTS (Optional) Java runtime options used when the "start",
30
rem
or "run" command is executed.
31
rem
32
rem
CATALINA_TMPDIR (Optional) Directory path location of temporary directory
33
rem
the JVM should use (java.io.tmpdir). Defaults to
34
rem
%CATALINA_BASE%\temp.
35
rem
36
rem
JAVA_HOME Must point at your Java Development Kit installation.
37
rem
Required to run the with the "debug" argument.
38
rem
39
rem
JRE_HOME Must point at your Java Runtime installation.
40
rem
Defaults to JAVA_HOME if empty.
41
rem
42
rem
JAVA_OPTS (Optional) Java runtime options used when the "start",
43
rem
"stop", or "run" command is executed.
44
rem
45
rem
JAVA_ENDORSED_DIRS (Optional) Lists of of semi-colon separated directories
46
rem
containing some jars in order to allow replacement of APIs
47
rem
created outside of the JCP (i.e. DOM and SAX from W3C).
48
rem
It can also be used to update the XML parser implementation.
49
rem
Defaults to $CATALINA_HOME/endorsed.
50
rem
51
rem
JPDA_TRANSPORT (Optional) JPDA transport used when the "jpda start"
52
rem
command is executed. The default is "dt_socket".
53
rem
54
rem
JPDA_ADDRESS (Optional) Java runtime options used when the "jpda start"
55
rem
command is executed. The default is 8000.
56
rem
57
rem
JPDA_SUSPEND (Optional) Java runtime options used when the "jpda start"
58
rem
command is executed. Specifies whether JVM should suspend
59
rem
execution immediately after startup. Default is "n".
60
rem
61
rem
JPDA_OPTS (Optional) Java runtime options used when the "jpda start"
62
rem
command is executed. If used, JPDA_TRANSPORT, JPDA_ADDRESS,
63
rem
and JPDA_SUSPEND are ignored. Thus, all required jpda
64
rem
options MUST be specified. The default is:
65
rem
66
rem
-agentlib:jdwp=transport=%JPDA_TRANSPORT%,
67
rem
address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%
68
rem
69
rem
LOGGING_CONFIG (Optional) Override Tomcat's logging config file
70
rem
Example (all one line)
71
rem
set LOGGING_CONFIG="-Djava.util.logging.config.file=%CATALINA_BASE%\conf\logging.properties"
72
rem
73
rem
LOGGING_MANAGER (Optional) Override Tomcat's logging manager
74
rem
Example (all one line)
75
rem
set LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
76
rem
77
rem
TITLE (Optional) Specify the title of Tomcat window. The default
78
rem
TITLE is Tomcat if it's not specified.
79
rem
Example (all one line)
80
rem
set TITLE=Tomcat.Cluster#1.Server#1 [%DATE% %TIME%]
81
rem
82
rem
83
rem
84
rem
$Id: catalina.bat 1040546 2010-11-30 14:47:34Z markt $
85
rem
---------------------------------------------------------------------------
86
87
rem
Suppress Terminate batch job on CTRL+C
88
if
not
""
%1
"" == ""
run
""
goto
mainEntry
89
if
""%TEMP%"" == """"
goto
mainEntry
90
if
exist
"%TEMP%\%~nx0.run"
goto
mainEntry
91
echo
Y>"%TEMP%\%~nx0.run"
92
if
not
exist
"%TEMP%\%~nx0.run"
goto
mainEntry
93
echo
Y>"%TEMP%\%~nx0.Y"
94
call
"%~f0" %* <"%TEMP%\%~nx0.Y"
95
rem
Use provided errorlevel
96
set
RETVAL=%
ERRORLEVEL
%
97
del
/Q "%TEMP%\%~nx0.Y" >NUL 2>&1
98
exit
/
B %RETVAL%
99
:mainEntry
100
del
/Q "%TEMP%\%~nx0.run" >NUL 2>&1
101
102
rem
Guess CATALINA_HOME if not defined
103
set
"CURRENT_DIR=%cd%"
104
if
not
"%CATALINA_HOME%" == ""
goto
gotHome
105
set
"CATALINA_HOME=%CURRENT_DIR%"
106
if
exist
"%CATALINA_HOME%\bin\catalina.bat"
goto
okHome
107
cd
..
108
set
"CATALINA_HOME=%cd%"
109
cd
"%CURRENT_DIR%"
110
:gotHome
111
if
exist
"%CATALINA_HOME%\bin\catalina.bat"
goto
okHome
112
echo
The CATALINA_HOME environment variable is
not
defined correctly
113
echo
This environment variable is needed to
run
this program
114
goto
end
115
:okHome
116
117
rem
Ensure that any user defined CLASSPATH variables are not used on startup,
118
rem
but allow them to be specified in setenv.bat, in rare case when it is needed.
119
set
CLASSPATH=
120
121
rem
Get standard environment variables
122
if
"%CATALINA_BASE%" == ""
goto
gotSetenvHome
123
if
exist
"%CATALINA_BASE%\bin\setenv.bat"
call
"%CATALINA_BASE%\bin\setenv.bat"
124
goto
gotSetenvBase
125
:gotSetenvHome
126
if
exist
"%CATALINA_HOME%\bin\setenv.bat"
call
"%CATALINA_HOME%\bin\setenv.bat"
127
:gotSetenvBase
128
129
rem
Get standard Java environment variables
130
if
exist
"%CATALINA_HOME%\bin\setclasspath.bat"
goto
okSetclasspath
131
echo
Cannot
find
"%CATALINA_HOME%\bin\setclasspath.bat"
132
echo
This file is needed to
run
this program
133
goto
end
134
:okSetclasspath
135
set
"BASEDIR=%CATALINA_HOME%"
136
call
"%CATALINA_HOME%\bin\setclasspath.bat"
%1
137
if
errorlevel
1
goto
end
138
139
rem
Add on extra jar file to CLASSPATH
140
rem
Note that there are no quotes as we do not want to introduce random
141
rem
quotes into the CLASSPATH
142
if
"%CLASSPATH%" == ""
goto
emptyClasspath
143
set
"CLASSPATH=%CLASSPATH%;"
144
:emptyClasspath
145
set
"CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\bootstrap.jar"
146
147
if
not
"%CATALINA_BASE%" == ""
goto
gotBase
148
set
"CATALINA_BASE=%CATALINA_HOME%"
149
:gotBase
150
151
if
not
"%CATALINA_TMPDIR%" == ""
goto
gotTmpdir
152
set
"CATALINA_TMPDIR=%CATALINA_BASE%\temp"
153
:gotTmpdir
154
155
rem
Add tomcat-juli.jar to classpath
156
rem
tomcat-juli.jar can be over-ridden per instance
157
if
not
exist
"%CATALINA_BASE%\bin\tomcat-juli.jar"
goto
juliClasspathHome
158
set
"CLASSPATH=%CLASSPATH%;%CATALINA_BASE%\bin\tomcat-juli.jar"
159
goto
juliClasspathDone
160
:juliClasspathHome
161
set
"CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\tomcat-juli.jar"
162
:juliClasspathDone
163
164
if
not
"%LOGGING_CONFIG%" == ""
goto
noJuliConfig
165
set
LOGGING_CONFIG=
-Dnop
166
if
not
exist
"%CATALINA_BASE%\conf\logging.properties"
goto
noJuliConfig
167
set
LOGGING_CONFIG=-Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties"
168
:noJuliConfig
169
set
JAVA_OPTS=
%JAVA_OPTS% %LOGGING_CONFIG%
170
171
if
not
"%LOGGING_MANAGER%" == ""
goto
noJuliManager
172
set
LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.juli.
ClassLoaderLogManager
173
:noJuliManager
174
set
JAVA_OPTS=
%JAVA_OPTS% %LOGGING_MANAGER%
175
176
rem
----- Execute The Requested Command ---------------------------------------
177
178
echo
Using CATALINA_BASE: "%CATALINA_BASE%"
179
echo
Using CATALINA_HOME: "%CATALINA_HOME%"
180
echo
Using CATALINA_TMPDIR: "%CATALINA_TMPDIR%"
181
if
""
%1
"" == ""
debug
""
goto
use_jdk
182
echo
Using JRE_HOME: "%JRE_HOME%"
183
goto
java_dir_displayed
184
:use_jdk
185
echo
Using JAVA_HOME: "%JAVA_HOME%"
186
:java_dir_displayed
187
echo
Using CLASSPATH: "%CLASSPATH%"
188
189
set
_EXECJAVA=
%_RUNJAVA%
190
set
MAINCLASS=org.apache.catalina.startup.
Bootstrap
191
set
ACTION=
start
192
set
SECURITY_POLICY_FILE=
193
set
DEBUG_OPTS=
194
set
JPDA=
195
196
if
not
""
%1
"" == ""jpda""
goto
noJpda
197
set
JPDA=
jpda
198
if
not
"%JPDA_TRANSPORT%" == ""
goto
gotJpdaTransport
199
set
JPDA_TRANSPORT=
dt_socket
200
:gotJpdaTransport
201
if
not
"%JPDA_ADDRESS%" == ""
goto
gotJpdaAddress
202
set
JPDA_ADDRESS=8000
203
:gotJpdaAddress
204
if
not
"%JPDA_SUSPEND%" == ""
goto
gotJpdaSuspend
205
set
JPDA_SUSPEND=
n
206
:gotJpdaSuspend
207
if
not
"%JPDA_OPTS%" == ""
goto
gotJpdaOpts
208
set
JPDA_OPTS=-agentlib
:jdwp
=transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=
%JPDA_SUSPEND%
209
:gotJpdaOpts
210
shift
211
:noJpda
212
213
if
""
%1
"" == ""
debug
""
goto
doDebug
214
if
""
%1
"" == ""
run
""
goto
doRun
215
if
""
%1
"" == ""
start
""
goto
doStart
216
if
""
%1
"" == ""stop""
goto
doStop
217
if
""
%1
"" == ""version""
goto
doVersion
218
219
echo
Usage: catalina ( commands ... )
220
echo
commands:
221
echo
debug
Start
Catalina in a debugger
222
echo
debug
-security
Debug
Catalina with a security manager
223
echo
jpda
start
Start
Catalina under JPDA debugger
224
echo
run
Start
Catalina in the current window
225
echo
run
-security
Start
in the current window with security manager
226
echo
start
Start
Catalina in a separate window
227
echo
start
-security
Start
in a separate window with security manager
228
echo
stop Stop Catalina
229
echo
version What version of tomcat are you running?
230
goto
end
231
232
:doDebug
233
shift
234
set
_EXECJAVA=
%_RUNJDB%
235
set
DEBUG_OPTS=-sourcepath "%CATALINA_HOME%\..\..\java"
236
if
not
""
%1
"" == ""-security""
goto
execCmd
237
shift
238
echo
Using Security Manager
239
set
"SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
240
goto
execCmd
241
242
:doRun
243
shift
244
if
not
""
%1
"" == ""-security""
goto
execCmd
245
shift
246
echo
Using Security Manager
247
set
"SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
248
goto
execCmd
249
250
:doStart
251
shift
252
if
not
"%OS%" == "Windows_NT"
goto
noTitle
253
if
"%TITLE%" == ""
set
TITLE=
Tomcat
254
set
_EXECJAVA=
start
"%TITLE%"
%_RUNJAVA%
255
goto
gotTitle
256
:noTitle
257
set
_EXECJAVA=
start
%_RUNJAVA%
258
:gotTitle
259
if
not
""
%1
"" == ""-security""
goto
execCmd
260
shift
261
echo
Using Security Manager
262
set
"SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
263
goto
execCmd
264
265
:doStop
266
shift
267
set
ACTION=
stop
268
set
CATALINA_OPTS=
269
goto
execCmd
270
271
:doVersion
272
%_EXECJAVA% -classpath "%CATALINA_HOME%\lib\catalina.jar" org.apache.catalina.util.
ServerInfo
273
goto
end
274
275
276
:execCmd
277
rem
Get remaining unshifted command line arguments and save them in the
278
set
CMD_LINE_ARGS=
279
:setArgs
280
if
""
%1
""==""""
goto
doneSetArgs
281
set
CMD_LINE_ARGS=%CMD_LINE_ARGS%
%1
282
shift
283
goto
setArgs
284
:doneSetArgs
285
286
rem
Execute Java with the applicable properties
287
if
not
"%JPDA%" == ""
goto
doJpda
288
if
not
"%SECURITY_POLICY_FILE%" == ""
goto
doSecurity
289
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
290
goto
end
291
:doSecurity
292
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
293
goto
end
294
:doJpda
295
if
not
"%SECURITY_POLICY_FILE%" == ""
goto
doSecurityJpda
296
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
297
goto
end
298
:doSecurityJpda
299
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
300
goto
end
301
302
:end
在第1行,和第17行中的內容已經在前一章中做出說明,在此處不再敖述,我對于18-85行的這段注釋比較感興趣:
1
rem
---------------------------------------------------------------------------
2
rem
Start/Stop Script for the CATALINA Server
3
rem
4
rem
Environment Variable Prerequisites
5
rem
6
rem
CATALINA_HOME May point at your Catalina "build" directory.
7
rem
8
rem
CATALINA_BASE (Optional) Base directory for resolving dynamic portions
9
rem
of a Catalina installation. If not present, resolves to
10
rem
the same directory that CATALINA_HOME points to.
11
rem
12
rem
CATALINA_OPTS (Optional) Java runtime options used when the "start",
13
rem
or "run" command is executed.
14
rem
15
rem
CATALINA_TMPDIR (Optional) Directory path location of temporary directory
16
rem
the JVM should use (java.io.tmpdir). Defaults to
17
rem
%CATALINA_BASE%\temp.
18
rem
19
rem
JAVA_HOME Must point at your Java Development Kit installation.
20
rem
Required to run the with the "debug" argument.
21
rem
22
rem
JRE_HOME Must point at your Java Runtime installation.
23
rem
Defaults to JAVA_HOME if empty.
24
rem
25
rem
JAVA_OPTS (Optional) Java runtime options used when the "start",
26
rem
"stop", or "run" command is executed.
27
rem
28
rem
JAVA_ENDORSED_DIRS (Optional) Lists of of semi-colon separated directories
29
rem
containing some jars in order to allow replacement of APIs
30
rem
created outside of the JCP (i.e. DOM and SAX from W3C).
31
rem
It can also be used to update the XML parser implementation.
32
rem
Defaults to $CATALINA_HOME/endorsed.
33
rem
34
rem
JPDA_TRANSPORT (Optional) JPDA transport used when the "jpda start"
35
rem
command is executed. The default is "dt_socket".
36
rem
37
rem
JPDA_ADDRESS (Optional) Java runtime options used when the "jpda start"
38
rem
command is executed. The default is 8000.
39
rem
40
rem
JPDA_SUSPEND (Optional) Java runtime options used when the "jpda start"
41
rem
command is executed. Specifies whether JVM should suspend
42
rem
execution immediately after startup. Default is "n".
43
rem
44
rem
JPDA_OPTS (Optional) Java runtime options used when the "jpda start"
45
rem
command is executed. If used, JPDA_TRANSPORT, JPDA_ADDRESS,
46
rem
and JPDA_SUSPEND are ignored. Thus, all required jpda
47
rem
options MUST be specified. The default is:
48
rem
49
rem
-agentlib:jdwp=transport=%JPDA_TRANSPORT%,
50
rem
address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%
51
rem
52
rem
LOGGING_CONFIG (Optional) Override Tomcat's logging config file
53
rem
Example (all one line)
54
rem
set LOGGING_CONFIG="-Djava.util.logging.config.file=%CATALINA_BASE%\conf\logging.properties"
55
rem
56
rem
LOGGING_MANAGER (Optional) Override Tomcat's logging manager
57
rem
Example (all one line)
58
rem
set LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
59
rem
60
rem
TITLE (Optional) Specify the title of Tomcat window. The default
61
rem
TITLE is Tomcat if it's not specified.
62
rem
Example (all one line)
63
rem
set TITLE=Tomcat.Cluster#1.Server#1 [%DATE% %TIME%]
64
rem
65
rem
66
rem
67
rem
$Id: catalina.bat 1040546 2010-11-30 14:47:34Z markt $
68
rem
---------------------------------------------------------------------------
這段的內容就是說明一下在啟動和停止CATALINA server時候需要的一下先決條件,CATALINA_HOME--看到這個大家可能會有點疑問,如果在操作系統上沒有設置CATALINA_HOME變量的時候,那么這個變量應該是不存在的丫,是怎么回事呢?是不是?下面我們還是用測試來說明問題:我在F:\apache-tomcat-7.0.8\bin目錄下創建一個test.bat文件,文件內容如下:
@echo
off
set
CURRENT_DIR=%
cd
%
test2
.bat
? ?意思很簡單,只是將%cd%變量的值賦給CURRENT_DIR變量,然后調用test2.bat文件,test2.bat文件的內容如下:
echo
%CURRENT_DIR%
? 只是簡單的輸出%CURRENT_DIR%變量,讓我們先運行test.bat文件,查看%CURRENT_DIR%變量是否能夠正確輸出:
? ? ? ?結果正確顯示了,但是如果我們直接運行test2.bat文件會有什么結果呢?
? ? ? 結果顯示不正常,這個測試就說明由test.bat調用test2.bat文件時候,test.bat中定義的變量在test2.bat中可見,就是CURRENT_DIR變量的生命周期范圍并不是僅限于本文件,也能加深對于setlocal方法的理解。回到catalina.bat本身,也許我們本身沒有設置CATALINA_HOME環境變量的習慣,但是回想一下上一節,在startup.bat中說到,如果沒有設置CATALINA_HOME變量,startup.bat內會給CATALINA_HOME變量賦值,然后在catalina.bat中依然能夠訪問此變量。
? ? ?這段注釋說完之后,看一下88行:?
if
not
""
%1
"" == ""
run
""
goto
mainEntry
如果接收到的第一個參數是run那么到:mainEntry節點,事實是我們從startup.bat調用的時候傳遞的第一個參數無疑是start,所以應該順序執行到第89行,這里可能有人會有疑問,那什么時候第一個參數才是run呢?事情是這樣的,因為并不是所有人都是跟我們一樣直接使用startup.bat文件啟動,因為startup.bat文件也只不過就是找到catalina.bat文件,然后照樣傳遞參數,其實有經驗的人大可直接使用catalina.bat文件來啟動tomcat。這就是第一個參數為run的產生情況。接下來我們順序執行到第89行。
? ? 看一下89行的內容:
if
""%TEMP%"" == """"
goto
mainEntry
?如果TEMP變量為空,那么到mainEntry節點,這個時候我們就需要看看我們到底有沒有這個TEMP變量,同樣弄個小測試,寫一個小的測試test.bat文件,文件內容如下:
@echo
off
echo
%TEMP%
查看執行結果:
?
? ? ? 記得在上一節中說過%TEMP%這個變量是從環境變量中讀取的,所以也可以去環境變量中查看是不是有此值,來確定TEMP變量是不是存在,一問在startup.bat和catalina.bat并沒有設置TEMP變量。查看環境變量:
? ? ?因為TEMP存在,所以程序還需要順序執行到90行,第90行的內容如下:? ?
if
exist
"%TEMP%\%~nx0.run"
goto
mainEntry
這句話至少看起來有點蒙圈,尤其是\%~nx0.run這個東西,反正我第一次看見的時候我就想問問,這是毛啊,~nx0,下面看一下網上對于%~nx0的解釋:
%~nx0 contains the name of the running batch file (without the
path
)
意思就是代表執行命令的文件的名字,我們來用實驗證明一下,同樣還是修改那個test.bat文件吧。;-)
@echo
off
echo
"%TEMP%\%~nx0.run"
如果按照上面的解釋,那么輸出的信息應該是C:\Users\Think\AppData\Local\Temp\test.bat.run,下面看一下運行結果:
咦事實證明說法正確,但是這個文件是不是存在呢,我們去TEMP目錄下看一下,遺憾的是在C:\Users\Think\AppData\Local\Temp目錄沒有找到這個文件,所以還得順序執行到第91行,91行的內容是:
echo
Y>"%TEMP%\%~nx0.run"
這個看起來很簡單,既然不存在這個文件,那么我就自己創建一個,同時寫入Y。也許你不信,所以我還是拿出個例子吧,還是test.bat呦:
@echo
off
echo
Y>"%TEMP%\%~nx0.run"
在C:\Users\Think\AppData\Local\Temp目錄下生成了test.bat.run文件,文件的內容果然為Y。至于生成的文件有何意義,以后再說。到現在位置我突然感慨,我很喜歡TOMCAT,它做了什么我都能知道,在接下來的一段時間內,我想把我看TOMCAT源代碼的感受也下下來。也跟大家討論一下TOMCAT的工作原理。有點遠,扯回來,下面看一下92行的內容:
if
not
exist
"%TEMP%\%~nx0.run"
goto
mainEntry
這個一眼就看明白了,再次判斷%~nx0.run文件是否存在,如果還是不存在,那么直接到mainEntry節點,由于我們此時此文件已經創建成功,那么順序執行到第93行。
93行的內容為:
echo
Y>"%TEMP%\%~nx0.Y"
這個同91行命令,不再強調。順序執行到92行。
92行的內容為:
call
"%~f0" %* <"%TEMP%\%~nx0.Y"
看到之后感覺依然是蒙圈,這里面有兩個點需要大家掌握:%~f0, %* 知道這兩組符號是什么意思,就解決了。
%~f0:表示運行的文件的全路徑,假如我在test.bat中如此寫:
@echo
off
@echo
%%~f0 is %~f0
那么執行結果為:
? ? ?OK。
%*:在batch file中,每一個命令的參數都以%1,%2,%3 .....的形式展現,我們也可以使用%來代替所有的參數,下面看修改萬能測試文件test.bat中的內容如下:
@echo
off
echo
First argument: [
%1
]
echo
Second argument: [
%2
]
echo
Third argument: [
%3
]
echo
Fourth argument: [
%4
]
echo
Fifth argument: [
%4
]
echo
Entire
command
line: [%*]
查看運行結果:
意思就是將在catalina.bat文件中自己調用自己,傳遞參數Y,下面看一下測試,將test.bat中的內容改為:
@echo
off
call
"%~f0" %* <"%TEMP%\%~nx0.Y"
查看運行結果,在程序運行了一段時間以后,得出如下結論:
很奇怪,奇怪亮點,為什么運行的時候會有停頓,第二,為什么會產生這個結果。下面解決這兩個困惑,我覺得程序在運行的時候肯定是在后臺運行什么操作了,所以我將test.bat中的內容改了一下: ?
call
"%~f0" %* <"%TEMP%\%~nx0.Y"
然后再次運行,得到結果:
原來程序在輸出最終結果之前一直到在調用自己,所以會有一個停頓的感覺。
第二:為什么會產生這個結果:
下面看第96行的內容:
set
RETVAL=%
ERRORLEVEL
%
在前面的的內容中可能給大家一種誤解,所以在看到這句話的時候,不知道是不是也有人跟我似的直接去環境變量中找ERRORLEVEL的值,找不到之后覺得我在忽悠大家,下面我跟大家說說這個ERRORLEVEL。不知道大家是不是了解在Linux中的$?這個結果返回值,其實ERRORLEVEL和$?差不多,都是用來表示上次執行結果的,如果返回0說明執行正確,如果不是0說明執行失敗。例如在test.bat中的內容:
call
%
ERRORLEVEL
%
執行結果:
下面看97行的內容:
del
/Q "%TEMP%\%~nx0.Y" >NUL 2>&1
這里面有/Q, >NUL, 2>&1需要跟大家解釋一下:
/Q: 跟在del后面表示不需要交互式的刪除。安靜模式的意思。如在test.bat中的內容如下:
del
/Q "%TEMP%\%~nx0.Y" >NUL 2>&1
然后運行結果為:
此時文件系統中的文件確實已經被刪除,只是在刪除的過程中沒有顯示刪除的過程,下面我們重新創建此文件,然后把/Q標記去掉以后在嘗試一次:
>NUL 就是將輸出輸出到NUL中,這樣有錯誤的情況下你什么都拿不到。
2>&1:2是值錯誤輸出,&1是標準輸出,意思就是將錯誤輸出重定向到標準輸出中
?>NUL 2>&1的意思就是將錯誤輸出重定向到標準輸出,最后在重定向到NUL中,這樣出現錯誤,你從表面上不會看出來。如果將test.bat中的刪除操作執行多次,
@echo
off
del
/Q "%TEMP%\%~nx0.Y" >NUL 2>&1
看結果:
也不會顯示異常,如果將>NUL 2>&1刪除以后,再次執行:
@echo
off
del
/Q "%TEMP%\%~nx0.Y"
結果就會顯示出異常:
下面看第98行的內容:
exit
/B %RETVAL%
? 下面的mainEntry和gotHome節點的信息同前一節剛開始的內容一樣,所有就不再說明,如果對此有什么疑問,請查看 查看tomcat啟動文件都干點啥 一節。在接下來的部分中我想把115-137行的內容放在一起說明,因為他們分為兩部分,分別引入setenv.bat和setclasspath.bat并執行,
:okHome
rem
Ensure that any user defined CLASSPATH variables are not used on startup,
rem
but allow them to be specified in setenv.bat, in rare case when it is needed.
set
CLASSPATH=
rem
Get standard environment variables
if
"%CATALINA_BASE%" == ""
goto
gotSetenvHome
if
exist
"%CATALINA_BASE%\bin\setenv.bat"
call
"%CATALINA_BASE%\bin\setenv.bat"
goto
gotSetenvBase
:gotSetenvHome
if
exist
"%CATALINA_HOME%\bin\setenv.bat"
call
"%CATALINA_HOME%\bin\setenv.bat"
:gotSetenvBase
rem
Get standard Java environment variables
if
exist
"%CATALINA_HOME%\bin\setclasspath.bat"
goto
okSetclasspath
echo
Cannot
find
"%CATALINA_HOME%\bin\setclasspath.bat"
echo
This file is needed to
run
this program
goto
end
:okSetclasspath
set
"BASEDIR=%CATALINA_HOME%"
call
"%CATALINA_HOME%\bin\setclasspath.bat"
%1
if
errorlevel
1
goto
end
這部分的操作就是設置環境變量,由于在tomcat7.0.8版本中不存在setenv.bat所以就不說了,setclasspath.bat這個腳本很重要,瀏覽一下其中的內容:
@echo
off
rem
Licensed to the Apache Software Foundation (ASF) under one or more
rem
contributor license agreements. See the NOTICE file distributed with
rem
this work for additional information regarding copyright ownership.
rem
The ASF licenses this file to You under the Apache License, Version 2.0
rem
(the "License"); you may not use this file except in compliance with
rem
the License. You may obtain a copy of the License at
rem
rem
http://www.apache.org/licenses/LICENSE-2.0
rem
rem
Unless required by applicable law or agreed to in writing, software
rem
distributed under the License is distributed on an "AS IS" BASIS,
rem
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rem
See the License for the specific language governing permissions and
rem
limitations under the License.
rem
---------------------------------------------------------------------------
rem
Set JAVA_HOME or JRE_HOME if not already set, ensure any provided settings
rem
are valid and consistent with the selected start-up options and set up the
rem
endorsed directory.
rem
rem
$Id: setclasspath.bat 964208 2010-07-14 21:24:45Z markt $
rem
---------------------------------------------------------------------------
rem
Make sure prerequisite environment variables are set
if
not
"%JAVA_HOME%" == ""
goto
gotJdkHome
if
not
"%JRE_HOME%" == ""
goto
gotJreHome
echo
Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
echo
At least one of these environment variable is needed to
run
this program
goto
exit
:gotJreHome
if
not
exist
"%JRE_HOME%\bin\java.exe"
goto
noJavaHome
if
not
exist
"%JRE_HOME%\bin\javaw.exe"
goto
noJavaHome
if
not
""
%1
"" == ""
debug
""
goto
okJavaHome
echo
JAVA_HOME should point to a JDK in order to
run
in
debug
mode
.
goto
exit
:gotJdkHome
if
not
exist
"%JAVA_HOME%\bin\java.exe"
goto
noJavaHome
if
not
exist
"%JAVA_HOME%\bin\javaw.exe"
goto
noJavaHome
if
not
exist
"%JAVA_HOME%\bin\jdb.exe"
goto
noJavaHome
if
not
exist
"%JAVA_HOME%\bin\javac.exe"
goto
noJavaHome
if
not
"%JRE_HOME%" == ""
goto
okJavaHome
set
"JRE_HOME=%JAVA_HOME%"
goto
okJavaHome
:noJavaHome
echo
The JAVA_HOME environment variable is
not
defined correctly
echo
This environment variable is needed to
run
this program
echo
NB: JAVA_HOME should point to a JDK
not
a JRE
goto
exit
:okJavaHome
if
not
"%BASEDIR%" == ""
goto
gotBasedir
echo
The BASEDIR environment variable is
not
defined
echo
This environment variable is needed to
run
this program
goto
exit
:gotBasedir
if
exist
"%BASEDIR%\bin\setclasspath.bat"
goto
okBasedir
echo
The BASEDIR environment variable is
not
defined correctly
echo
This environment variable is needed to
run
this program
goto
exit
:okBasedir
rem
Don't override the endorsed dir if the user has set it previously
if
not
"%JAVA_ENDORSED_DIRS%" == ""
goto
gotEndorseddir
rem
Set the default -Djava.endorsed.dirs argument
set
"JAVA_ENDORSED_DIRS=%BASEDIR%\endorsed"
:gotEndorseddir
rem
Set standard command for invoking Java.
rem
Note that NT requires a window name argument when using start.
rem
Also note the quoting as JAVA_HOME may contain spaces.
set
_RUNJAVA="%JRE_HOME%\bin\java"
set
_RUNJDB="%JAVA_HOME%\bin\jdb"
goto
end
:exit
exit
/b 1
:end
exit
/b 0
其中就是關于JAVA環境的一些校驗和變量的設置,重要性不言而喻,所以如果執行本步操作失敗的情況下,程序將退出執行。
接下來是設置CLASSPATH的內容,看過前面的說明以后,對于下面的內容應該很容易就能看懂:
rem
Add on extra jar file to CLASSPATH
rem
Note that there are no quotes as we do not want to introduce random
rem
quotes into the CLASSPATH
if
"%CLASSPATH%" == ""
goto
emptyClasspath
set
"CLASSPATH=%CLASSPATH%;"
:emptyClasspath
set
"CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\bootstrap.jar"
if
not
"%CATALINA_BASE%" == ""
goto
gotBase
set
"CATALINA_BASE=%CATALINA_HOME%"
:gotBase
if
not
"%CATALINA_TMPDIR%" == ""
goto
gotTmpdir
set
"CATALINA_TMPDIR=%CATALINA_BASE%\temp"
:gotTmpdir
rem
Add tomcat-juli.jar to classpath
rem
tomcat-juli.jar can be over-ridden per instance
if
not
exist
"%CATALINA_BASE%\bin\tomcat-juli.jar"
goto
juliClasspathHome
set
"CLASSPATH=%CLASSPATH%;%CATALINA_BASE%\bin\tomcat-juli.jar"
goto
juliClasspathDone
:juliClasspathHome
set
"CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\tomcat-juli.jar"
:juliClasspathDone
將tomcat-juli.jar和bootstrap.jar的全路徑追加到CLASSPATH中,究竟這兩個jar包是做什么的,不是本文的范疇,只說明這兩個jar包需要在CLASSPATH中體現。
接下來是關于Log選項的問題:
if
not
"%LOGGING_CONFIG%" == ""
goto
noJuliConfig
set
LOGGING_CONFIG=
-Dnop
if
not
exist
"%CATALINA_BASE%\conf\logging.properties"
goto
noJuliConfig
set
LOGGING_CONFIG=-Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties"
:noJuliConfig
set
JAVA_OPTS=
%JAVA_OPTS% %LOGGING_CONFIG%
if
not
"%LOGGING_MANAGER%" == ""
goto
noJuliManager
set
LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.juli.
ClassLoaderLogManager
:noJuliManager
set
JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%
內容很簡單,一看就明白,所以也不多說了。
在前面準備了這么久,接下來終于到執行的時候了。下面看一下這段腳本:
rem
----- Execute The Requested Command ---------------------------------------
echo
Using CATALINA_BASE: "%CATALINA_BASE%"
echo
Using CATALINA_HOME: "%CATALINA_HOME%"
echo
Using CATALINA_TMPDIR: "%CATALINA_TMPDIR%"
if
""
%1
"" == ""
debug
""
goto
use_jdk
echo
Using JRE_HOME: "%JRE_HOME%"
goto
java_dir_displayed
:use_jdk
echo
Using JAVA_HOME: "%JAVA_HOME%"
:java_dir_displayed
echo
Using CLASSPATH: "%CLASSPATH%"
set
_EXECJAVA=
%_RUNJAVA%
set
MAINCLASS=org.apache.catalina.startup.
Bootstrap
set
ACTION=
start
set
SECURITY_POLICY_FILE=
set
DEBUG_OPTS=
set
JPDA=
if
not
""
%1
"" == ""jpda""
goto
noJpda
set
JPDA=
jpda
if
not
"%JPDA_TRANSPORT%" == ""
goto
gotJpdaTransport
set
JPDA_TRANSPORT=
dt_socket
:gotJpdaTransport
if
not
"%JPDA_ADDRESS%" == ""
goto
gotJpdaAddress
set
JPDA_ADDRESS=8000
:gotJpdaAddress
if
not
"%JPDA_SUSPEND%" == ""
goto
gotJpdaSuspend
set
JPDA_SUSPEND=
n
:gotJpdaSuspend
if
not
"%JPDA_OPTS%" == ""
goto
gotJpdaOpts
set
JPDA_OPTS=-agentlib
:jdwp
=transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=
%JPDA_SUSPEND%
:gotJpdaOpts
shift
:noJpda
if
""
%1
"" == ""
debug
""
goto
doDebug
if
""
%1
"" == ""
run
""
goto
doRun
if
""
%1
"" == ""
start
""
goto
doStart
if
""
%1
"" == ""stop""
goto
doStop
if
""
%1
"" == ""version""
goto
doVersion
echo
Usage: catalina ( commands ... )
echo
commands:
echo
debug
Start
Catalina in a debugger
echo
debug
-security
Debug
Catalina with a security manager
echo
jpda
start
Start
Catalina under JPDA debugger
echo
run
Start
Catalina in the current window
echo
run
-security
Start
in the current window with security manager
echo
start
Start
Catalina in a separate window
echo
start
-security
Start
in a separate window with security manager
echo
stop Stop Catalina
echo
version What version of tomcat are you running?
goto
end
:doDebug
shift
set
_EXECJAVA=
%_RUNJDB%
set
DEBUG_OPTS=-sourcepath "%CATALINA_HOME%\..\..\java"
if
not
""
%1
"" == ""-security""
goto
execCmd
shift
echo
Using Security Manager
set
"SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto
execCmd
:doRun
shift
if
not
""
%1
"" == ""-security""
goto
execCmd
shift
echo
Using Security Manager
set
"SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto
execCmd
:doStart
shift
if
not
"%OS%" == "Windows_NT"
goto
noTitle
if
"%TITLE%" == ""
set
TITLE=
Tomcat
set
_EXECJAVA=
start
"%TITLE%"
%_RUNJAVA%
goto
gotTitle
:noTitle
set
_EXECJAVA=
start
%_RUNJAVA%
:gotTitle
if
not
""
%1
"" == ""-security""
goto
execCmd
shift
echo
Using Security Manager
set
"SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto
execCmd
:doStop
shift
set
ACTION=
stop
set
CATALINA_OPTS=
goto
execCmd
:doVersion
%_EXECJAVA% -classpath
"%CATALINA_HOME%\lib\catalina.jar" org.apache.catalina.util.
ServerInfo
goto
end
:execCmd
rem
Get remaining unshifted command line arguments and save them in the
set
CMD_LINE_ARGS=
:setArgs
if
""
%1
""==""""
goto
doneSetArgs
set
CMD_LINE_ARGS=%CMD_LINE_ARGS%
%1
shift
goto
setArgs
:doneSetArgs
rem
Execute Java with the applicable properties
if
not
"%JPDA%" == ""
goto
doJpda
if
not
"%SECURITY_POLICY_FILE%" == ""
goto
doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:doJpda
if
not
"%SECURITY_POLICY_FILE%" == ""
goto
doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:end
前三行的內容是將當前設置的變量進行輸出,
echo
Using CATALINA_BASE: "%CATALINA_BASE%"
echo
Using CATALINA_HOME: "%CATALINA_HOME%"
echo
Using CATALINA_TMPDIR: "%CATALINA_TMPDIR%"
CATALINA_BASE,CATALINA_HOME,CATALINA_TMPDIR這三個變量在startup.bat或者catalina.bat中已經提前設置了,射出只是為了提示用戶當前的運行環境,接下來看181-187行的內容:
if
""
%1
"" == ""
debug
""
goto
use_jdk
echo
Using JRE_HOME: "%JRE_HOME%"
goto
java_dir_displayed
:use_jdk
echo
Using JAVA_HOME: "%JAVA_HOME%"
:java_dir_displayed
echo
Using CLASSPATH: "%CLASSPATH%"
在解釋這段內容之前,我建議大家要對setclasspath.bat中的內容有所了解,因為setclasspath.bat中包含對與JRE_HOME,JAVA_HOME變量的邏輯處理和定義。這段內容的意思就是說如果catalina.bat接收到的第一個參數是debug,那么就到use_jdk節點,由于一般情況下我們是用startup.bat腳本調用catalina.bat腳本,所以第一個參數應該是start,所以應該順序執行到182行 echo Using JRE_HOME: "%JRE_HOME%",然后執行到java_dir_displayed節點,至于為什么 debug的時候不使用JRE_HOME這個變量 ,我們先記下,在以后的章節中在討論。
在189-194行中是設置一些變量,內容如下:
set
_EXECJAVA=
%_RUNJAVA%
set
MAINCLASS=org.apache.catalina.startup.
Bootstrap
set
ACTION=
start
set
SECURITY_POLICY_FILE=
set
DEBUG_OPTS=
set
JPDA=
這里面要說兩點,%_RUNJAVA%變量和org.apache.catalina.startup.Bootstrap,其中%_RUNJAVA%是在setclasspath.bat文件中定義的,其值為"%JRE_HOME%\bin\java",
MAINCLASS寫過JAVA程序的人應該都知道是做什么用的,關鍵是org.apache.catalina.startup.Bootstrap這個值是怎么來的,在哪里定義的,記得在catalina.bat中有過這么一個設置:CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\bootstrap.jar,其中org.apache.catalina.startup.Bootstrap就是該jar包中的一個類。具體內容以及意義不再此展開。
第196行-211行是對jpda()的處理,因為咱們沒有涉及,關于jdpa的內容不在此展開,因為我們不涉及所以跳過此步驟:
if
not
""
%1
"" == ""jpda""
goto
noJpda
set
JPDA=
jpda
if
not
"%JPDA_TRANSPORT%" == ""
goto
gotJpdaTransport
set
JPDA_TRANSPORT=
dt_socket
:gotJpdaTransport
if
not
"%JPDA_ADDRESS%" == ""
goto
gotJpdaAddress
set
JPDA_ADDRESS=8000
:gotJpdaAddress
if
not
"%JPDA_SUSPEND%" == ""
goto
gotJpdaSuspend
set
JPDA_SUSPEND=
n
:gotJpdaSuspend
if
not
"%JPDA_OPTS%" == ""
goto
gotJpdaOpts
set
JPDA_OPTS=-agentlib
:jdwp
=transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=
%JPDA_SUSPEND%
:gotJpdaOpts
shift
:noJpda
再次記下一個知識點JDPA。
下面到noJpda節點,內容如下:
if
""
%1
"" == ""
debug
""
goto
doDebug
if
""
%1
"" == ""
run
""
goto
doRun
if
""
%1
"" == ""
start
""
goto
doStart
if
""
%1
"" == ""stop""
goto
doStop
if
""
%1
"" == ""version""
goto
doVersion
echo
Usage: catalina ( commands ... )
echo
commands:
echo
debug
Start
Catalina in a debugger
echo
debug
-security
Debug
Catalina with a security manager
echo
jpda
start
Start
Catalina under JPDA debugger
echo
run
Start
Catalina in the current window
echo
run
-security
Start
in the current window with security manager
echo
start
Start
Catalina in a separate window
echo
start
-security
Start
in a separate window with security manager
echo
stop Stop Catalina
echo
version What version of tomcat are you running?
goto
end
其中
if
""
%1
"" == ""
debug
""
goto
doDebug
if
""
%1
"" == ""
run
""
goto
doRun
if
""
%1
"" == ""
start
""
goto
doStart
if
""
%1
"" == ""stop""
goto
doStop
if
""
%1
"" == ""version""
goto
doVersion
是根據用戶輸入的具體命令,跳轉到具體的處理節點,例如輸入的命令,那么就到doStart節點,219行-230行的內容是,如果你輸入的第一個參數不再預設的命令當中,給你的提示:
echo
Usage: catalina ( commands ... )
echo
commands:
echo
debug
Start
Catalina in a debugger
echo
debug
-security
Debug
Catalina with a security manager
echo
jpda
start
Start
Catalina under JPDA debugger
echo
run
Start
Catalina in the current window
echo
run
-security
Start
in the current window with security manager
echo
start
Start
Catalina in a separate window
echo
start
-security
Start
in a separate window with security manager
echo
stop Stop Catalina
echo
version What version of tomcat are you running?
goto
end
下面先看232行-240行的doDebug節點的內容:
:doDebug
shift
set
_EXECJAVA=
%_RUNJDB%
set
DEBUG_OPTS=-sourcepath "%CATALINA_HOME%\..\..\java"
if
not
""
%1
"" == ""-security""
goto
execCmd
shift
echo
Using Security Manager
set
"SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto
execCmd
同樣%_RUNJDB%變量去setclasspath.bat文件中找定義,235行的內容配置DEBUG_OPTS,接下來是安全策略的問題,如果指定參數"-security",那么就需要加載安全策略文件,安全策略文件為%CATALINA_BASE%\conf\catalina.policy,內容如下:
// Licensed to the Apache Software Foundation (ASF)
under one or more
// contributor license agreements.
See the NOTICE file distributed with
// this work
for
additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may
not
use
this file except in compliance with
// the License. You may obtain a
copy
of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
software
// distributed under the License is distributed
on
an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License
for
the specific language governing permissions and
// limitations under the License.
// ============================================================================
// catalina.policy - Security Policy Permissions
for
Tomcat 7
//
// This file contains a default
set
of security policies to be enforced (
by the
// JVM)
when
Catalina is executed with the "-security" option.
In addition
// to the permissions granted here,
the following additional permissions are
//
granted specific to each web application:
//
//
* Read access to its document root directory
// * Read,
write and delete access to its working directory
//
// $Id: catalina.policy 981453 2010-08-02 11:00:51Z markt $
// ============================================================================
// ========== SYSTEM CODE PERMISSIONS =========================================
//
These permissions apply to javac
grant codeBase
"file:${java.home}/lib/-"
{
permission java
.security.AllPermission;
}
;
//
These permissions apply to all shared system extensions
grant codeBase
"file:${java.home}/jre/lib/ext/-"
{
permission java
.security.AllPermission;
}
;
// These permissions apply to javac
when
${java.home] points at $JAVA_HOME/
jre
grant codeBase
"file:${java.home}/../lib/-"
{
permission java
.security.AllPermission;
}
;
// These permissions apply to all shared system extensions
when
// ${java.home} points at $JAVA_HOME/
jre
grant codeBase
"file:${java.home}/lib/ext/-"
{
permission java
.security.AllPermission;
}
;
// ========== CATALINA CODE PERMISSIONS =======================================
//
These permissions apply to the daemon code
grant codeBase
"file:${catalina.home}/bin/commons-daemon.jar"
{
permission java
.security.AllPermission;
}
;
//
These permissions apply to the logging API
// Note:
If
tomcat-juli.jar is in ${catalina.base} and
not
in ${catalina.home},
// update this section accordingly.
// grant codeBase "file:${catalina.base}/bin/tomcat-juli.jar" {..
}
grant codeBase
"file:${catalina.home}/bin/tomcat-juli.jar"
{
permission java
.io.
FilePermission
"${java.home}${file.separator}lib${file.separator}logging.properties", "read";
permission java
.io.
FilePermission
"${catalina.base}${file.separator}conf${file.separator}logging.properties", "read";
permission java
.io.
FilePermission
"${catalina.base}${file.separator}logs", "read, write";
permission java
.io.
FilePermission
"${catalina.base}${file.separator}logs${file.separator}*", "read, write";
permission java
.lang.RuntimePermission "shutdownHooks";
permission java
.lang.RuntimePermission "getClassLoader";
permission java
.lang.RuntimePermission "setContextClassLoader";
permission java
.util.logging.LoggingPermission "control";
permission java
.util.PropertyPermission "java.util.logging.config.class", "read";
permission java
.util.PropertyPermission "java.util.logging.config.file", "read";
permission java
.util.PropertyPermission "catalina.base", "read";
// Note: To enable per context logging configuration,
permit read access to
// the appropriate file.
Be sure that the logging configuration is
// secure before enabling such access.
// E.g.
for
the examples web application:
// permission java.io.FilePermission "
${catalina.base}${file.separator}
// webapps${file.separator}examples${file.separator}WEB-INF
// ${file.separator}classes${file.separator}logging.properties
", "read";
}
;
//
These permissions apply to the server startup code
grant codeBase
"file:${catalina.home}/bin/bootstrap.jar"
{
permission java
.security.AllPermission;
}
;
//
These permissions apply to the servlet API classes
//
and those that are shared across all class loaders
// located in the "lib"
directory
grant codeBase
"file:${catalina.home}/lib/-"
{
permission java
.security.AllPermission;
}
;
//
If
using a per instance lib directory, i.e. ${catalina.base}/lib,
//
then
the following permission will need to be uncommented
// grant codeBase "file:${catalina.base}/lib/-"
{
// permission java.security.AllPermission;
// };
// ========== WEB APPLICATION PERMISSIONS =====================================
//
These permissions are granted by default to all web applications
// In addition,
a web application will be given a read FilePermission
// and JndiPermission
for
all
files
and directories in its document root.
grant {
// Required
for
JNDI lookup of named JDBC DataSource's and
//
javamail named MimePart DataSource used to send mail
permission java
.util.PropertyPermission "java.home", "read";
permission java
.util.PropertyPermission "java.naming.*", "read";
permission java
.util.PropertyPermission "javax.sql.*", "read";
//
OS Specific properties to allow read access
permission java
.util.PropertyPermission "os.name", "read";
permission java
.util.PropertyPermission "os.version", "read";
permission java
.util.PropertyPermission "os.arch", "read";
permission java
.util.PropertyPermission "file.separator", "read";
permission java
.util.PropertyPermission "path.separator", "read";
permission java
.util.PropertyPermission "line.separator", "read";
//
JVM properties to allow read access
permission java
.util.PropertyPermission "java.version", "read";
permission java
.util.PropertyPermission "java.vendor", "read";
permission java
.util.PropertyPermission "java.vendor.url", "read";
permission java
.util.PropertyPermission "java.class.version", "read";
permission java
.util.PropertyPermission "java.specification.version", "read";
permission java
.util.PropertyPermission "java.specification.vendor", "read";
permission java
.util.PropertyPermission "java.specification.name", "read";
permission java
.util.PropertyPermission "java.vm.specification.version", "read";
permission java
.util.PropertyPermission "java.vm.specification.vendor", "read";
permission java
.util.PropertyPermission "java.vm.specification.name", "read";
permission java
.util.PropertyPermission "java.vm.version", "read";
permission java
.util.PropertyPermission "java.vm.vendor", "read";
permission java
.util.PropertyPermission "java.vm.name", "read";
// Required
for
OpenJMX
permission java
.lang.RuntimePermission "getAttribute";
// Allow read of JAXP compliant XML parser
debug
permission java
.util.PropertyPermission "jaxp.debug", "read";
//
All JSPs need to be able to read this package
permission java
.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat";
// Precompiled JSPs need access to these packages.
permission java
.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.el";
permission java
.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime";
permission java
.lang.
RuntimePermission
"accessClassInPackage.org.apache.jasper.runtime.*";
// Precompiled JSPs need access to these system properties.
permission java
.util.
PropertyPermission
"org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER", "read";
permission java
.util.
PropertyPermission
"org.apache.el.parser.COERCE_TO_ZERO", "read";
// The cookie code needs these.
permission java
.util.
PropertyPermission
"org.apache.catalina.STRICT_SERVLET_COMPLIANCE", "read";
permission java
.util.
PropertyPermission
"org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING", "read";
permission java
.util.
PropertyPermission
"org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR", "read";
//
Applications using Comet need to be able to access this package
permission java
.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.comet";
}
;
//
The Manager application needs access to the following packages to support the
//
session display functionality
grant codeBase
"file:${catalina.base}/webapps/manager/-"
{
permission java
.lang.RuntimePermission "accessClassInPackage.org.apache.catalina";
permission java
.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager";
permission java
.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager.util";
}
;
// You can
assign
additional permissions to particular web applications by
// adding additional "grant" entries here, based
on
the code base
for
that
// application, /WEB-INF/classes/, or /WEB-INF/lib/ jar
files
.
//
// Different permissions can be granted to JSP pages,
classes loaded from
// the /WEB-INF/classes/ directory, all jar
files
in the /WEB-INF/lib/
// directory, or even to individual jar
files
in the /WEB-INF/lib/ directory.
//
//
For
instance, assume that the standard "examples"
application
//
included a JDBC driver that needed to establish a network connection to the
//
corresponding database and used the scrape taglib to get the weather from
// the NOAA web server. You might create a "grant"
entries like this:
//
// The permissions granted to the context root directory apply to JSP pages.
// grant codeBase "file:${catalina.base}/webapps/examples/-"
{
// permission java.
net
.SocketPermission "dbhost.mycompany.com:5432", "connect";
// permission java.
net
.SocketPermission "*.noaa.gov:80", "connect";
// };
//
// The permissions granted to the context WEB-INF/
classes directory
// grant codeBase "file:${catalina.base}/webapps/examples/WEB-INF/classes/-"
{
// };
//
//
The permission granted to your JDBC driver
// grant codeBase "jar:file:${catalina.base}/webapps/examples/WEB-INF/lib/driver.jar!/-"
{
// permission java.
net
.SocketPermission "dbhost.mycompany.com:5432", "connect";
// };
//
The permission granted to the scrape taglib
// grant codeBase "jar:file:${catalina.base}/webapps/examples/WEB-INF/lib/scrape.jar!/-"
{
// permission java.
net
.SocketPermission "*.noaa.gov:80", "connect";
// };
里面涉及到一些權限的設置,有興趣大家可以仔細研究。最終執行execCmd節點的腳本。
242行-248行doRun節點內容如下:
:doRun
shift
if
not
""
%1
"" == ""-security""
goto
execCmd
shift
echo
Using Security Manager
set
"SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto
execCmd
內容同doDebug內容相似,只是判斷是不是需要加載安全配置文件。
250行-263行的doStart節點:
:doStart
shift
if
not
"%OS%" == "Windows_NT"
goto
noTitle
if
"%TITLE%" == ""
set
TITLE=
Tomcat
set
_EXECJAVA=
start
"%TITLE%"
%_RUNJAVA%
goto
gotTitle
:noTitle
set
_EXECJAVA=
start
%_RUNJAVA%
:gotTitle
if
not
""
%1
"" == ""-security""
goto
execCmd
shift
echo
Using Security Manager
set
"SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto
execCmd
主要內容就是,如果%OS%環境變量不是Windows_NT,那么不設置標題,直接判斷是否需要加載安全配置文件,如果%OS%環境變量的值為Windows_NT,那么設置Title變量,如果沒有指定Title變量,默認值為Tomcat,設置完_EXECJAVA變量以后,執行execCmd節點的腳本。
265行-269行的doStop節點,內容比較簡單,主要就是設置一下ACTION變量,內容如下:
:doStop
shift
set
ACTION=
stop
set
CATALINA_OPTS=
goto
execCmd
271行-273行的doVersion節點,就是調用了一下"%CATALINA_HOME%\lib\catalina.jar"中的org.apache.catalina.util.ServerInfo方法,內容如下:
:doVersion
%_EXECJAVA% -classpath
"%CATALINA_HOME%\lib\catalina.jar" org.apache.catalina.util.
ServerInfo
goto
end
下面真正的重點來了,execCmd節點,其中有和startup.bat中處理參與一樣功能的節點setArgs,從279行-283行,循環讀出參數中的內容追加到CMD_LINE_ARGS變量中,內容如下:
set
CMD_LINE_ARGS=
:setArgs
if
""
%1
""==""""
goto
doneSetArgs
set
CMD_LINE_ARGS=%CMD_LINE_ARGS%
%1
shift
goto
setArgs
286行-300行的內容就是真正的執行方法了,先看內容:
rem
Execute Java with the applicable properties
if
not
"%JPDA%" == ""
goto
doJpda
if
not
"%SECURITY_POLICY_FILE%" == ""
goto
doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:doJpda
if
not
"%SECURITY_POLICY_FILE%" == ""
goto
doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
是不是有點長,是不是有點看不懂,是不是覺得很麻煩,不要著急,我想一個辦法,更直觀的觀察這里面究竟是什么東西:下面我在這些腳本上添點東西,弄成這個樣子:
rem
Execute Java with the applicable properties
if
not
"%JPDA%" == ""
goto
doJpda
if
not
"%SECURITY_POLICY_FILE%" == ""
goto
doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
echo
1 %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
echo
2 %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:doJpda
if
not
"%SECURITY_POLICY_FILE%" == ""
goto
doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
echo
3 %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava
.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
echo
4 %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%"
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto
end
:end
pause
其實很簡單,就是把內容輸出,然后為了能看清,我在后面加了個pause,嘿嘿,下面我從startup.bat啟動catalina.bat以后看輸出結果:
Using CATALINA_BASE: "F:\apache-tomcat-7.0.8"
Using CATALINA_HOME:
"F:\apache-tomcat-7.0.8"
Using CATALINA_TMPDIR:
"F:\apache-tomcat-7.0.8\temp"
Using JRE_HOME:
"E:\Program Files\Java\jdk1.7.0_40"
Using CLASSPATH:
"
F:\apache-tomcat-7.0.8\bin\bootstrap.jar;F:\apache-tomca
t-7.0.8\bin\tomcat-juli.jar
"
1
start
"Tomcat" "E:\Program Files\Java\jdk1.7.0_40\bin\java" -Djava.util.
loggi
ng
.config.file="F:\apache-tomcat-7.0.8\conf\logging.properties" -Djava.util.
logg
ing
.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs="
F:\apa
che-tomcat-7.0.8\endorsed
" -classpath "
F:\apache-tomcat-7.0.8\bin\bootstrap.jar;
F:\apache-tomcat-7.0.8\bin\tomcat-juli.jar
" -Dcatalina.base="
F:\apache-tomcat-7.
0.8
" -Dcatalina.home="F:\apache-tomcat-7.0.8" -Djava.io.tmpdir="
F:\apache-tomcat
-7.0.8\temp
" org.apache.catalina.startup.Bootstrap
start
請按任意鍵繼續
. . .
分析一下結果得出如下結論:
_EXECJAVA=
start
"Tomcat" "E:\Program Files\Java\jdk1.7.0_40\bin\java"
JAVA_OPTS
= -Djava.util.logging.config.file="F:\apache-tomcat-7.0.8\conf\logging.properties"
-Djava
.util.logging.manager=org.apache.juli.
ClassLoaderLogManager
CATALINA_OPTS
=
DEBUG_OPTS
=
-Djava
.endorsed.dirs="F:\apache-tomcat-7.0.8\endorsed"
-classpath
"F:\apache-tomcat-7.0.8\bin\bootstrap.jar;F:\apache-tomcat-7.0.8\bin\tomcat-juli.jar"
-Dcatalina
.base="F:\apache-tomcat-7.0.8"
-Dcatalina
.home="F:\apache-tomcat-7.0.8"
-Djava
.io.tmpdir="F:\apache-tomcat-7.0.8\temp"
MAINCLASS
=org.apache.catalina.startup.
Bootstrap
CMD_LINE_ARGS
= ACTION=
start
至于其他情況,大家自己研究吧,希望能起到拋磚引玉的作用。在文中有三處疑問(標紅加粗字體),由于和本文關心不太大,在以后說明,如果誰愿意交流也可以寫在評論中, 昨天晚上寫了這些,腦袋都混亂了,好像如果有不正確的地方,歡迎大家指認。
?
?
?
?
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

