當(dāng)logstash啟動時,首先要注意正確配置java
并且最近版本的logstash要求java8
在搞定以上后確認(rèn)環(huán)境變量沒有問題
再確認(rèn)logstash所在的目錄 不存在含有空格的文件夾名稱
在這所有所有之后還是會報錯:找不到或無法加載主類 (亂序地址)
解決方案
廢話不多說:找到logstash/bin目錄下的logstash.bat
打開編輯,找到如下行
%JAVA% %JAVA_OPTS% -cp "%CLASSPATH%" org.logstash.Logstash %*
這行與你的應(yīng)該有所區(qū)別,沒錯
將%CLASSPATH%改為"%CLASSPATH%"即可解決
讓我學(xué)習(xí)一下批處理寫法 理解一下這行為什么這樣,之后,有空再解釋原因
2018年3月9日17:19:19更新
產(chǎn)生原因
PS G:\Users\XXX\Desktop> ./logstash.bat
錯誤: 找不到或無法加載主類 Files\Java\jdk1.8.0_161\lib;G:"Program
以上是錯誤命令運行的輸出 可以看到 找不到或無法加載主類,而后跟著的目錄為
Files\Java\jdk1.8.0_161\lib;G:"Program
因為我的jdk 放在G:\Program Files\java\jdk1.8.0_161\lib下了,因此一開始百思不得其解,什么錯誤會產(chǎn)生位置字符串中間截斷然后顛倒這種迷之錯誤。
因為logstash啟動文件是個批處理,這樣調(diào)試起來就很方便在,在各行插入pause語句調(diào)試,最后將錯誤定位到52行
%JAVA% %JAVA_OPTS% -cp %CLASSPATH% org.logstash.Logstash %*
今天學(xué)習(xí)了一下批處理語法,這一句無非是將一些變量組合成為新的語句再執(zhí)行而已,那么錯誤不在批處理程序,因為自己再寫批處理的話難保拿到的變量與運行時完全一樣所以直接在logstash.bat中插入了一些語句將其輸出(因為沒那么多時間閱讀全文,前面已經(jīng)提到了直接定位到了出錯是這一句)
%JAVA% %JAVA_OPTS% -cp %CLASSPATH% org.logstash.Logstash %*
pause
echo %JAVA% >>a.txt
echo " " >>a.txt
echo %JAVA_OPTS%>>a.txt
echo " " >>a.txt
echo %CLASSPATH%>>a.txt
echo " " >>a.txt
echo %*>>a.txt
echo " " >>a.txt
echo "%CLASSPATH%" >>a.txt
pause
將上面的語句改寫成這樣,將變量全部輸出到a.txt,檢查該文件
"G:\Program Files\Java\jdk1.8.0_161\bin\java.exe"
-Xms1------很長的字符串------/urandom
.;G:\Program Files\Java\jdk1.8.0_161\lib;G:\Program Files\Java\jdk1.8.0_161\lib\tools.jar;"E:\logstash-6.2.2\logstash-core\lib\jars\animal-sniffer-annotations-1.14.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\commons-compiler-3.0.8.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\error_prone_annotations-2.0.18.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\google-java-format-1.5.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\guava-22.0.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\j2objc-annotations-1.1.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\jackson-annotations-2.9.1.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\jackson-core-2.9.1.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\jackson-databind-2.9.1.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\jackson-dataformat-cbor-2.9.1.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\janino-3.0.8.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\javac-shaded-9-dev-r4023-3.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\jruby-complete-9.1.13.0.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\jsr305-1.3.9.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\log4j-api-2.9.1.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\log4j-core-2.9.1.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\log4j-slf4j-impl-2.9.1.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\logstash-core.jar";"E:\logstash-6.2.2\logstash-core\lib\jars\slf4j-api-1.7.25.jar"
-f ../config/pipeline.conf
抱歉我知道上面這坨太冗雜了但是相信我,比較重要吧。
觀察上面這些輸出,再結(jié)合logstash.bat中的實際語序,可以發(fā)現(xiàn)這實際上是一句簡單的java程序啟動的cmd.
java -opt1 -opt2 -cp "classpath" org.logstash.Logstash -f ../config/pipeline.conf
那么到這一步 再結(jié)合錯誤輸出為找不到或無法加載主類,可以猜測是-cp 之后的classpath出現(xiàn)了問題。
仔細(xì)觀察classpath,發(fā)現(xiàn)一些問題,該字符串明顯為拼接字符串,然而有些地址用雙引號("")括起來了,有些沒有。再觀察,可以發(fā)現(xiàn)括起來的為logstash自己的jar包,沒有的則為系統(tǒng)本身的CLASSPATH環(huán)境變量的值。
猜測由雙引號引起該問題,再加上前面的解決方案是在整個%CLASSPATH%變量外面加 "" 可以猜測為系統(tǒng)本身的CLASSPATH沒有加上雙引號引起的,按照他的style將雙引號加在每個地址上,問題解決。
繼續(xù)研究?;氐?strong>logstash/bat文件,發(fā)現(xiàn)
:concat
IF not defined CLASSPATH (
set CLASSPATH="%~1"
) ELSE (
set CLASSPATH=%CLASSPATH%;"%~1"
)
很明顯 該代碼段產(chǎn)生了整個批處理文件中實際調(diào)用的CLASSPATH
調(diào)用該代碼段的地方是
for %%i in ("%LS_HOME%\logstash-core\lib\jars\*.jar") do (
call :concat "%%i"
)
很容易懂的一個循環(huán),對logstash目錄下的\logstash-core\lib\jars\下的所有jar包循環(huán),將包名作為參數(shù)執(zhí)行上上的那個代碼段,即
將logstash jar包目錄下的所有jar包的所在路徑連接到系統(tǒng)本身的CLASSPATH路徑之后
那么到此CLASSPATH的產(chǎn)生方式已經(jīng)很明顯了,錯誤也很明顯了,產(chǎn)生CLASSPATH時,因為系統(tǒng)中有CLASSPATH變量因此直接執(zhí)行ELSE部分,將系統(tǒng)變量通過 "%CLASSPATH%" 的方式直接讀取,在之后加上;"%~1"
這里%~1的作用是取第一個參數(shù)并去掉雙引號,第一個參數(shù)是循環(huán)的當(dāng)時系數(shù),而去掉雙引號之后又加上了雙引號所以最后的結(jié)果是有雙引號的,這也就是我們看到的 調(diào)用的CLASSPATH后面的logstash的包都有雙引號的原因。而在循環(huán)第一次執(zhí)行的時候,直接用了系統(tǒng)的%CLASSPATH%這里是沒有雙引號的,因此結(jié)果也沒有(不能在這里加雙引號,因為隨著循環(huán),引號會被遞歸加上,整個路徑會亂掉)
這里有一個另外的思考,前面的輸出a.txt文件可以看到,直接用%JAVA%輸出的java.exe所在目錄實際上竟然是有雙引號的,而我自己寫了個批處理 "echo %JAVA%顯示的是echo 開關(guān)狀態(tài),證明找不到JAVA這個系統(tǒng)變量,這是顯然的,但是我在logstash.bat中竟然沒有找到對變量JAVA的set操作,也就是說找不到這個JAVA地址是在何處獲得并賦值的,也就無法研究java.exe的路徑為何是有雙引號的。
重要的解釋
我認(rèn)為還需要解釋一下為什么不加引號就會炸,大家還記得最開始的錯誤輸出吧
PS G:\Users\XXX\Desktop> ./logstash.bat
錯誤: 找不到或無法加載主類 Files\Java\jdk1.8.0_161\lib;G:"Program
這其實并不是地址斷掉了或者說倒置了,而是Program FIile 中間有一個空格,批處理文件以空格作為分格符,由于我的jdk放置在系統(tǒng)盤的program file文件夾下,因此我的環(huán)境變量的classpath中有兩個包含空格的路徑,批處理命令將第一個空格前的內(nèi)容作為java -cp命令中的classpath地址傳入, 后兩個空格間的"Files\Java\jdk1.8.0_161\lib;G:"Program"自然就作為主類傳入了,因此產(chǎn)生了如此奇怪的輸出。而解決空格的方法就是:
將有空格或其他特殊字符的字符串用("")括起來