Shell 教學
Shell 是一個用 C 語言編寫的程式,它是使用者使用 Linux 的橋樑。Shell 既是一種命令語言,又是一種程式設計語言。
Shell 是指一種應用程式,這個應用程式提供了一個介面,使用者通過這個介面存取操作系統內核的服務。
Ken Thompson 的 sh 是第一種 Unix Shell,Windows Explorer 是一個典型的圖形介面 Shell。
Shell 指令碼
Shell 指令碼(shell script),是一種爲 shell 編寫的指令碼程式。
業界所說的 shell 通常都是指 shell 指令碼,但讀者朋友要知道,shell 和 shell script 是兩個不同的概念。
由於習慣的原因,簡潔起見,本文出現的 「shell程式設計」 都是指 shell 指令碼程式設計,不是指開發 shell 自身。
等號設定變數
變數名=變數內容
$ 讀取,單引號中$ 變數名,雙引號中$ 變數名、$ {變數名}都可
$ 變數名、$ {變數名}
$ n,n代表第幾個數位
$ 0 爲執行的檔名,其餘代表第n個參數
$ n
算術運算子
+ 加
- 減
* 乘
/ 初
= 賦值
== 相等
!= 不相等
關係運算符
-eq 相等返回 true
-ne 不相等返回 true
-gt >返回 true
-lt <返回 true
-ge >=返回 true
-le <=返回 true
布爾運算子
! 非運算
-o 或運算
-a 與運算
邏輯運算子
&& AND
|| OR
字串運算子
= 兩個字串相等返回 true [ $a = $b ]
!= 不相等返回 true
-z 字串長度爲0返回 true
-n 字串長度不爲 0 返回 true
$ 字串s不爲空返回 true。
echo,輸出字串
echo string
if else-if else
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
for 回圈
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
while 語句
while condition
do
command
done
switch case
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
[ function ] funname [()]
{
action;
[return int;]
}
參數
$# 傳遞到指令碼或函數的參數個數
$* 以一個單字串顯示所有向指令碼傳遞的參數
$$ 指令碼執行的當前進程ID號
$! 後臺執行的最後一個進程的ID號
$@ 與$*相同,但是使用時加引號,並在引號中返回每個參數。
$- 顯示Shell使用的當前選項,與set命令功能相同。
$? 顯示最後命令的退出狀態。0表示沒有錯誤,其他任何值表明有錯誤。
command > file 將輸出重定向到 file。
command < file 將輸入重定向到 file。
command >> file 將輸出以追加的方式重定向到 file。
windows下編譯的shell檔案,每一行的結尾是\n\r,而在linux下檔案的結尾是\n
檔案放入linux後,用以下命令解決
$ sed -i 's/\r$//' 檔名
# export:用於設定或顯示環境變數
# export [-fnp][變數名稱]=[變數設定值]
export JAVA_HOME=/usr/java/jdk1.8.0_11
export JRE_HOME=$JAVA_HOME/jre
# 變數賦值,反斜槓爲跳脫
# API_NAME+JAR_NAME 包名
API_NAME=helloworld
JAR_NAME=$API_NAME\.jar
# 啓動日誌名
LOG_NAME=$API_NAME\.log
#PID 代表是PID檔案
PID=$API_NAME\.pid
# 方法:使用說明,用來提示輸入參數
formatDescription() {
# echo:輸出字串
# -e:開啓跳脫
echo -e "===============Please use the following format==================\n"
echo -e ">>> sh service.sh [start|debug|stop|restart|status] <<<"
echo -e "\n==============================================================="
# exit 0:正常執行程式並退出程式;
# exit 1:非正常執行導致退出程式;
exit 1
}
# 方法:檢查程式是否在執行
checkStatus(){
# ps -ef|grep $JAR_NAME 匹配進程中包名
# grep -v 參數 : 過濾 匹配參數
# awk '{print $2}' 匹配第二個參數
# $0 就是你寫的shell指令碼本身的名字
# $1 是你給你寫的shell指令碼傳的第一個參數
# $2 是你給你寫的shell指令碼傳的第二個參數
pid=`ps -ef|grep $JAR_NAME|grep -v grep|awk '{print $2}' `
# if then、elif then、else、fi
# [ -z STRING ] 「STRING」 的長度爲零則爲真
# 如果不存在返回1,存在返回0
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
# 方法:啓動方法
startService(){
# 呼叫shell內的方法
checkStatus
# $?:獲取函數返回值或者上一個命令的退出狀態
# -eq : 等於
if [ $? -eq "0" ]; then
echo ">>> ${JAR_NAME} is already running, PID=${pid} <<<"
else
# nohup + & :後臺執行
# >$LOG_NAME : 將日誌資訊輸出到log日誌中
# 0 表示stdin標準輸入
# 1 表示stdout標準輸出
# 2 表示stderr標準錯誤
# & 相當於等效於標準輸出
# 2>&1 是將標準錯誤資訊轉變成標準輸出,這樣就可以將錯誤資訊輸出到out.log 日誌裏面來
# -noverify:關閉位元組碼驗證
# java -jar XXX.jar :執行jar
nohup $JRE_HOME/bin/java -noverify -Xms512m -Xmx1024m -jar $JAR_NAME >$LOG_NAME 2>&1 &
# $! Shell最後執行的後臺Process的PID
# '>' 爲建立: echo 「hello shell」 > out.txt
# '>>' 爲追加:echo 「hello shell」 >> out.txt
# 將進程的pid輸出到.pid檔案中(PID=$API_NAME\.pid)
echo $! > $PID
echo ">>> ${JAR_NAME} start successfully, PID=$! <<<"
fi
}
# 方法:debug方法
debugService(){
checkStatus
if [ $? -eq "0" ]; then
echo ">>> ${JAR_NAME} is already running, PID=${pid} <<<"
else
nohup $JRE_HOME/bin/java -agentlib:jdwp=transport=dtSocket,server=y,suspend=n,address=5006 -Xms512m -Xmx1024m -jar $JAR_NAME >$LOG_NAME 2>&1 &
echo $! > $PID
echo ">>> ${JAR_NAME} start in debug mode successfully, PID=$! <<<"
fi
}
# 方法:停止方法
stopService(){
# cat讀取PID檔案
pidf=$(cat $PID)
#echo "$pidf"
echo ">>> ${JAR_NAME} begin kill, $pidf <<<"
# kill 殺進程
kill $pidf
# rm -rf : 刪除檔案
rm -rf $PID
# 休眠3s
sleep 3
checkStatus
if [ $? -eq "0" ]; then
echo ">>> kill failed, kill it forcefully <<<"
echo ">>> ${JAR_NAME} begin kill -9 $pid <<<"
# kill -9 強制殺進程
kill -9 $pid
sleep 3
# 無需確認,進程biss
echo ">>> ${JAR_NAME} has been killed <<<"
else
echo ">>> ${JAR_NAME} has stopped <<<"
fi
}
# 方法:重新啓動
restartService(){
stopService
startService
}
# 方法:輸出執行狀態
statusService(){
checkStatus
if [ $? -eq "0" ]; then
echo ">>> ${JAR_NAME} is running, PID=${pid} <<<"
else
echo ">>> ${JAR_NAME} is not running <<<"
fi
}
# 根據輸入參數,選擇執行對應方法,不輸入則執行使用說明
# case expression in
# pattern 1)
# statement1
# ;;
# pattern 2)
# statement2
# ;;
# ……
# *)
# statementn
# esac
case "$1" in
"start")
startService
;;
"stop")
stopService
;;
"status")
statusService
;;
"restart")
restartService
;;
"debug")
debugService
;;
*)
formatDescription
;;
esac
exit 0
export JAVA_HOME=/usr/java/jdk1.8.0_11
export JRE_HOME=$JAVA_HOME/jre
API_NAME=helloworld
JAR_NAME=$API_NAME\.jar
LOG_NAME=$API_NAME\.log
PID=$API_NAME\.pid
formatDescription() {
echo -e "===============Please use the following format==================\n"
echo -e ">>> sh service.sh [start|debug|stop|restart|status] <<<"
echo -e "\n==============================================================="
exit 1
}
checkStatus(){
pid=`ps -ef|grep $JAR_NAME|grep -v grep|awk '{print $2}' `
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
startService(){
checkStatus
if [ $? -eq "0" ]; then
echo ">>> ${JAR_NAME} is already running, PID=${pid} <<<"
else
nohup $JRE_HOME/bin/java -noverify -Xms512m -Xmx1024m -jar $JAR_NAME >$LOG_NAME 2>&1 &
echo $! > $PID
echo ">>> ${JAR_NAME} start successfully, PID=$! <<<"
fi
}
debugService(){
checkStatus
if [ $? -eq "0" ]; then
echo ">>> ${JAR_NAME} is already running, PID=${pid} <<<"
else
nohup $JRE_HOME/bin/java -agentlib:jdwp=transport=dtSocket,server=y,suspend=n,address=5006 -Xms512m -Xmx1024m -jar $JAR_NAME >$LOG_NAME 2>&1 &
echo $! > $PID
echo ">>> ${JAR_NAME} start in debug mode successfully, PID=$! <<<"
fi
}
stopService(){
pidf=$(cat $PID)
echo ">>> ${JAR_NAME} begin kill, $pidf <<<"
kill $pidf
rm -rf $PID
sleep 3
checkStatus
if [ $? -eq "0" ]; then
echo ">>> kill failed, kill it forcefully <<<"
echo ">>> ${JAR_NAME} begin kill -9 $pid <<<"
kill -9 $pid
sleep 3
echo ">>> ${JAR_NAME} has been killed <<<"
else
echo ">>> ${JAR_NAME} has stopped <<<"
fi
}
restartService(){
stopService
startService
}
statusService(){
checkStatus
if [ $? -eq "0" ]; then
echo ">>> ${JAR_NAME} is running, PID=${pid} <<<"
else
echo ">>> ${JAR_NAME} is not running <<<"
fi
}
case "$1" in
"start")
startService
;;
"stop")
stopService
;;
"status")
statusService
;;
"restart")
restartService
;;
"debug")
debugService
;;
*)
formatDescription
;;
esac
exit 0