問題產生: 作者最近在搭建Hadoop+Hive集群時,將NameNode、DataNode、Rm全部部署到一臺物理機上,查詢量較大時連接掛掉。 問題定位: 使用JPS命令查看Metastore服務正常運行,hive2--Runjar掛掉。重啟之後,過段時間又會掛掉。 Linux 內核有個機制叫OO ...
掰碎了講一個jar包啟動文件.
- 當前服務目錄如下
# ls /easy/test/info/ -> bin mytest.jar
# ls /easy/test/info/bin/ -> spring-boot.sh
spring-boot.sh 文件內容如下
#!/bin/bash
# 環境索引: 標識解釋器為bash ./當前文件 等同於 sh 當前文件
# 本次解析執行命令= ./easy/test/info/bin/spring-boot.sh start
JAVA_OPTIONS_INITIAL=-Xms500M
JAVA_OPTIONS_MAX=-Xmx1000M
# 定義變數: 註意=左右不要有空格
BINPATH=$(cd `dirname $0`; pwd)
# 獲取腳本所在的項目名稱
# $0 獲取當前腳本本身的名字,其他包執行則包含到當前文件的路徑
# dirname 命令去除文件名中的非目錄部分,僅顯示與目錄有關的內容
# $()和反引號``的作用結果相同都是用來作命令替換的,通俗來講就是把命令執行後的結果作為參數返回
# pwd 命令用於顯示工作目錄的絕對路徑名稱
# 先執行 dirname $0 獲取當前目錄名稱,
# 再執行cd 切換到當前目錄,
# ; 分號; 用分號隔開兩個命令
# 再執行pwd, 用BINPATH 接受pwd返回結果.
# $0 ==> ./easy/test/info/bin/spring-boot.sh
# `dirname $0` ==> ./easy/test/info/bin/
# BINPATH==> /easy/test/info/bin
if [ $(ls ${BINPATH%/bin*}|grep .*.jar|wc -l) -gt 1 ] ;then
# 字元串截取: ${parameter%word} # 刪除匹配尾碼
# ${BINPATH%/bin*} 獲取BINPATH 刪除/bin 後面部分
# grep 匹配
# wc 計數
# -gt 大於
# if 流程判斷
# 獲取腳本上級的.jar 結尾文件是否>1個.
echo "目錄中含有多個jar文件"
exit 0
fi
_JAR_KEYWORDS=$(ls ${BINPATH%/bin*}|grep .*.jar)
# 獲取當前jar包名稱(mytest.jar)
if [ "$_JAR_KEYWORDS" = "" ] ;then
echo "${BINPATH%/bin*}下未找到jar包!!"
exit 0
fi
APP_NAME=${_JAR_KEYWORDS%.jar*}
# 字元串截取: ${parameter%word} # 刪除匹配尾碼
# ${_JAR_KEYWORDS%.jar*} 去掉jar包的.jar尾碼, 賦值給appName欄位(mytest)
if [ $1 == "start" ] ;then
echo "當前啟動的項目為:$APP_NAME,項目所在目錄:${BINPATH%/bin*}"
fi
# 查詢進程,去掉grep查詢, 取第二位(pid)
PID=$(ps aux | grep ${_JAR_KEYWORDS} | grep -v grep | awk '{print $2}' )
# ps 進程查看
# | grep -v grep 排除grep 進程,即當前的ps查詢進程
# awk 行處理器, awk '{print $2}' 輸出第2行數據, 即pid行.
function check_if_process_is_running {
if [ "$PID" = "" ]; then
return 1
fi
ps -p $PID | grep "java"
# ps 進程查看, 根據pid查看進程
return $?
# $? 上一指令的返回值,成功是0,不成功是1。
}
case "$1" in
status)
# case 選擇命令
# $1 執行該文件的第一個參數.
if check_if_process_is_running
then
echo -e "\033[32m $APP_NAME is running \033[0m"
# echo -e 轉義輸出
# \033[xm 控制字元 \033[32m 指定當前文本綠色展示.
else
echo -e "\033[32m $APP_NAME not running \033[0m"
fi
;;
stop)
if ! check_if_process_is_running
then
echo -e "\033[32m $APP_NAME already stopped \033[0m"
exit 0
fi
kill -9 $PID
# kill 殺死指定進程
echo -e "\033[32m Waiting for process to stop \033[0m"
NOT_KILLED=1
for i in {1..20}; do
if check_if_process_is_running
then
echo -ne "\033[32m . \033[0m"
# echo -ne 轉義輸出, 不進行換行
sleep 1
else
NOT_KILLED=0
fi
done
echo
if [ $NOT_KILLED = 1 ]
then
echo -e "\033[32m Cannot kill process \033[0m"
exit 1
fi
echo -e "\033[32m $APP_NAME already stopped \033[0m"
;;
start)
if [ "$PID" != "" ] && check_if_process_is_running
then
echo -e "\033[32m $APP_NAME already running \033[0m"
exit 1
fi
cd ${BINPATH%/bin*}
JAVA_MEM_SIZE_OPTS="-Xmx256m -Xms128m -Xmn256m -XX:PermSize=200m -XX:MaxPermSize=200M -Xss256k"
JAVA_MEM_OPTS=" -server $JAVA_MEM_SIZE_OPTS -XX:SurvivorRatio=2 -XX:+UseParallelGC "
nohup java -jar $JAVA_OPTIONS_INITIAL $JAVA_OPTIONS_MAX $_JAR_KEYWORDS --debug> 123.log 2>&1 &
#nohup 不掛起執行
echo -ne "\033[32m Starting \033[0m"
for i in {1..20}; do
# 通配符(globbing) {1..20} 迴圈20次,分別取1,2,3...19,20
echo -ne "\033[32m.\033[0m"
sleep 1
done
if check_if_process_is_running
then
echo -e "\033[32m $APP_NAME fail \033[0m"
else
echo -e "\033[32m $APP_NAME started \033[0m"
fi
;;
restart)
$0 stop
# 重新執行該文件, 傳遞參數為 stop
if [ $? = 1 ]
then
exit 1
fi
$0 start
# 重新執行該文件, 傳遞參數為 start
;;
*)
# case 未匹配, 走的預設模組
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit 0
-
環境索引
開頭"#!/bin/bash"作用 這行註釋的作用就是聲明解析當前文件要使用的解釋器
- 不聲明解釋器的方式
執行: sh xxx
- 聲明"#!/bin/bash"
執行: ./xxx(等同於 sh xxx)
- 聲明"#!/bin/cat"
執行: ./xxx(等同於 cat xxx)
-
變數定義和使用
- 定義變數
定義變數, 變數名不加美元符號$ your_name="easy.com" 註意,變數名和等號之間不能有空格,這可能和你熟悉的所有編程語言都不一樣。
- 使用一個定義過的變數
在變數名前面加美元符號即可: your_name="qinjx" echo $your_name echo ${your_name} 變數名外面的花括弧可選,加花括弧是為了幫助解釋器識別變數的邊界,比如下麵這種情況 for skill in Ada Coffe Action Java; do echo "I am good at ${skill}Script" # 識別為: skill echo "I am good at $skillScript" # 自動識別為: skillScript done
-
linux中$用法
- $0, $?等表示各種參數
$0:bash文件名。 $?:上一指令的返回值,成功是0,不成功是1。 $1,$2,$3....:表示命令後接的第幾個參數
- ${}, 獲取變數的值
${var_name} 跟光$var_name差不多 但是用${ }會比較精確的界定變數名稱的範圍。
- $(),`` 命令替換
在bash中,$( )與` `(反引號)都是用來作命令替換的,執行括弧或者反引號中的命令, 然後返回結果。 比如:echo "present dir is $(pwd)" 但是$()和``還是稍有不同的,在多層次的複合替換中,``必須要額外的跳脫處理(反斜線),而$( )則不用,比較直觀。 # 將cmd1執行結果作為cmd2參數,再將cmd2結果作為cmd3的參數 cmd1 $(cmd2 $(cmd3)) # 如果是用反引號,直接引用是不行的,還需要作跳脫處理 cmd1 `cmd2 \`cmd3\``
-
Linux 特殊字元用法(;,|,&,||,&&)
; 分號; 用分號隔開兩個命令,每條命令按照從左到右的順序,順序執行,彼此之間不關心是否失敗,所有命令都會執行。
| 管道符; 上一條命令的輸出,作為下一條命令參數
示例: grep "123" 1.txt | wc -l
& 放在啟動命令參數後面表示設置此進程為後臺進程
|| 邏輯或
只有在 || 左邊的命令返回假,右邊的命令才會被執行。
只要有一個命令返回真,後面的命令都不會被執行。一直到返回真的地方停止執行
&& 邏輯與
前一條命令執行成功,才會執行下一條命令。
-
linux ${}文本處理
- 獲取字元串長度 $
- 字元串切片$
將字元串變數a從第b個位置開始向後截取c個字元,b是指下標,下標從0開始
- 替換字元串$
將變數a中的b全部替換為c,開頭一個正斜杠為只匹配第一個字元串,兩個正斜杠為匹配所有字元。 b支持正則示例: echo ${a//[^0-9]/c}
- 字元串截取
${parameter#word} # 刪除匹配首碼 ${parameter##word} ${parameter%word} # 刪除匹配尾碼 ${parameter%%word} # 去掉左邊,#最短匹配模式,##最長匹配模式。 % 去掉右邊,%最短匹配模式,%%最長匹配模式。
- 變數狀態賦值
${VAR:-string} 如果 VAR 變數為空則返回 string ${VAR:+string} 如果 VAR 變數不為空則返回 string ${VAR:=string} 如果 VAR 變數為空則重新賦值 VAR 變數值為 string ${VAR:?string} 如果 VAR 變數為空則將 string 輸出到 stderr
-
基本運算符
- 算術運算符(+ - * / % = == !=)
- 關係運算符
-eq //equals等於 -ne //no equals不等於 -gt //greater than 大於 -lt //less than小於 -ge //greater equals大於等於 -le //less equals小於等於
- 布爾運算符
! 非運算,表達式為 true 則返回 false,否則返回 true。 -o 或運算,有一個表達式為 true 則返回 true。 -a 與運算,兩個表達式都為 true 才返回 true。
- 整數運算命令(())
雙小括弧 (( )) 是 Bash Shell 中專門用來進行整數運算的命令 註意:(( )) 只能進行整數運算,不能對小數(浮點數)或者字元串進行運算。後續講到的 bc 命令可以用於小數運算。 在 (( )) 中使用變數無需加上$首碼,(( )) 會自動解析變數名,這使得代碼更加簡潔,也符合程式員的書寫習慣 這種寫法可以在計算完成後給變數賦值 示例: ((b=a-15)) 將 a-15 的運算結果賦值給變數 b。 使用變數時不用加$首碼,(( )) 會自動解析變數名. 可以在 (( )) 前面加上$符號獲取 (( )) 命令的執行結果,也即獲取整個表達式的值 示例: b=$((a-15)) 將 a-15 的運算結果賦值給變數 b。 類似 c=((a+b)) 這樣的寫法是錯誤的,不加$就不能取得表達式的結果 (( )) 也可以進行邏輯運算,在 if 語句中常會使用邏輯運算。 示例: ((a>7 && b==c)) 不用寫 -gt -eq 等命令, 直接用數學寫法即可.
-
流程式控制制
- if 判斷
if xxx ; then xxx ; fi if xxx ; then xxx ; else xxx ; fi if xxx ; then xxx ; elif xxx ; then xxx ; else xxx ; fi
- for 迴圈
for xxx in xxx; do xxx done;
- while 迴圈執行
while xxx ; do xxx done; while true;do curl --request POST --url http://127.0.0.1:8111/api/healthy/post; sleep 1; done
- case 選擇
case xxx in x)xxx; ;;*)xxx; ;;esac 每個 case 取值後面必須為單詞 in, 分支用右圓括弧開始,用兩個分號 ;; 表示 break,即執行結束; * 匹配所有
- 無限迴圈
while:; do xxx ;done while true;do xxx ;done for ((;;));do xxx ;done
- 跳出迴圈(break,continue)
-
常用命令
- pwd:(print work directory)命令用於顯示工作目錄的絕對路徑名稱。
- grep 命令用於查找文件里符合條件的字元串
詳見: grep --help 具體見: info grep
- wc命令用於計算字數。
詳情見: wc --help 具體見: info wc -c或--bytes或--chars 只顯示Bytes數。 -l或--lines 顯示行數。 -w或--words 只顯示字數。
- awk 行處理器
詳情見: awk 具體見: info awk 示例: | awk '{print $1}' 以空格/tab作為分隔符,獲取第2個字元
- ps 進程查看器
詳情見: for i in s l o t m a ; do ps --help $i ;done 示例: ps -ef |grep xxx ps aux |grep xxx
- echo 字元串輸出
詳情見: help echo 選項: -n 不要追加換行 -e 啟用下列反斜杠轉義的解釋 -E 顯式地抑制對於反斜杠轉義的解釋 echo "string" # 輸出字元串 echo -e "開啟轉義" echo -e "xxx\n" # 添加換行 ehco -e "xxx\c" # 強制不換行
- \033[xxxm 控制字元
多個參數採用;分割. \033[0m 關閉所有屬性 \033[1m 設置高亮度 \033[30~37m 設置前景色 \033[40~47;m 設置背景色 示例: echo -e "\033[31;1m 這是一個紅色高亮文字 \033[0m" 顏色編碼示例: 黑=30,40 紅=31,41 綠=32,42 黃=33,43 藍=34,44 紫=35,45 靛藍=36,46 白=37,47
- 通配符(globbing)
示例: # for i in {1..20};do echo -n "$i," ;done 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, # ls {ex{1..3},ex4}.sh ex1.sh ex2.sh ex3.sh ex4.sh # ls {ex[1-3],ex4}.sh ex1.sh ex2.sh ex3.sh ex4.sh
- sleep 睡眠等待
詳見: sleep --help sleep 1 # 程式睡眠1秒
- nohup 不掛起(no hang up)
用於在系統後臺不掛斷地運行命令,退出終端不會影響程式的運行 詳見: nohup --help 示例1: nohup COMMAND > nohup.out 2>&1 & 2>&1 解釋: 將標準錯誤 2 重定向到標準輸出 &1 ,標準輸出 &1 再被重定向輸入到 nohup.out 文件中。 0 – stdin (standard input,標準輸入) 1 – stdout (standard output,標準輸出) 2 – stderr (standard error,標準錯誤輸出) 示例2: nohup COMMAND > /dev/null 2>&1 & # /dev/null 文件不存在則不進行控制台信息輸出.
- kill 殺死進程
詳見: kill --help 信號名稱: kill -l 常見信號: 1 (HUP):重新載入進程。 9 (KILL):殺死一個進程。 15 (TERM):正常停止一個進程。 強制殺死指定進程 kill -9 $(ps -ef |grep spring-boot)
日常用shell命令集合
- 測試環境,docker部署, 每次啟動生成一個新的日誌文件包, 想直接自動選擇到最後一個生成的文件包併進入
cd `ls -t`
# 效果: ll -lrt 選擇最後一個文件夾, copy文件名稱 cd ${fileName} 回車.
- 殺死指定項目啟動的進程
kill -9 $(ps -ef |grep xxxxxx)
# 效果: ps -ef |grep xxxxx 選擇pid行, 執行 kill -9 ${pid}
- 將指定文件copy到jar包內並重新啟動
ll
mkdir BOOT-INF
mkdir BOOT-INF/lib
mkdir BOOT-INF/classes
yes | mv *SNAPSHOT.jar BOOT-INF/lib
yes | mv *.properties BOOT-INF/classes
yes | mv *.yml BOOT-INF/classes
yes | mv *.xml BOOT-INF/classes
ll
jar uvf0 *.jar BOOT-INF/
rm -rf BOOT-INF
ll
sh bin/spring-boot.sh restart
date
# 效果:
# 將*SNAPSHOT.jar 的jar包copy到 BOOT-INF/lib目錄
# 將 *.properties 的 properties文件copy到BOOT-INF/classes目錄
# 將 *.yml 的 yml文件copy到BOOT-INF/classes目錄
# 將 *.xml 的 xml文件copy到BOOT-INF/classes目錄
# 將 BOOT-INF 壓縮到jar包內.
# 刪除臨時包, 並重啟, 列印當前日期