一些寫指令碼經驗, 僅供參考, 對於寫 jenkins 指令碼和運維有用
指令碼檔案
#! /bin/bash
# scripts write here
變數
# 賦值 = 兩邊不能有空格
var=xxx
# 區域性變數; 預設全是全域性變數
local var=xxx
# 引數, 從指令碼外來的引數為 $1, $2, $3 ; 一般在指令碼開始將其重新命名賦值
param1=$1
# 陣列 用空格分開
array=(var1 var2 var3)
# 變數中的變數;
image=app
appTar=/home/apps/app.tar
image_path=$(eval echo '$'${image}'Tar')
load_result=`docker load < $image_path`
# 字串拼接
# shell 中的字串拼接不用任何連線符, 直接寫後面就可以
var1=xx
var2=bbb
var3="${var1}${var2}foo"
echo $var3
輸出
# echo 列印不換行
echo -n "輸出字元"
輸入
# 輸入提示
read -p "提示語: " var
echo $var
# 輸入陣列, 每個項要用空格分隔
read -p "input array: " array
for ((i=0; i<${#array[@]}; i++)){
item=${array[i]}
echo $item
}
# 輸入目錄, 輸入目錄時可以使用 tab
read -p "input dir: " -e path
echo $path
程式控制
if 分支
# if空格[空格<變數>空格==空格<變數>空格];空格then
if [ "x" == "x${version}" ]; then
# do if
else
# do else
fi
條件判斷中, 由於 shell 對於>
<
等字元敏感, 所以, 大於, 小於寫成 gt lt 形式
case 分支
case $var in
"value1")
# do value1
;;
"*")
# do not catch
;;
esac
case 分支一般用來處理選擇分支程式, 如果輸入項沒有滿足要求, 則最後列印使用說明
usage() {
echo "Usage: sh server.sh [start|stop]"
exit 1
}
case "$1" in
"start")
start
;;
"stop")
stop
;;
"*")
usage
;;
esac
for 迴圈
array=(1 2 3)
for ((i=0; i<${#array[@]}; i++)){
item=${array[i]}
echo $item
}
這種 for 迴圈比較符合常規程式語言, 所以我一般喜歡用這個 for 迴圈
用 find 命令查到的檔案, 可以使用 for in 來操作
sqlfiles=`find . -name "*.sql"`
for sqlfile in $sqlfiles
do
echo $sqlfile
done
函式
# 函式宣告, 也需要先宣告才能使用
function fun(){
param1=$1
param2=$2
# some scripts
result=xxx
return 1
}
# 函式呼叫
fun "mm" 1
echo $?
echo "fun result is: $result"
shell 中函式的引數和返回值和其它程式中不太一樣
引數: 和 shell 指令碼一樣, 引數名為 $1 $2 $3 ...
返回值: 只能返回數字, 呼叫處使用 $? 接收 表示上條命令的執行結果; 注意: 要立即接收, 這個只能表示上一條命令的執行結果, 不然下一條命令一執行, 這個值就沒了
一般使用全域性變數來傳遞函式的返回值, 因為它的返回值功能實在是太弱了
模組
單獨的功能另啟指令碼來寫, 呼叫另一個指令碼
sh script.sh
引數: 和調指令碼引數一樣 $1 $2 $3
返回值: 返回值需要使用 export 暴露出來, 呼叫處的指令碼才能訪問到
export var=xxxx
刪除命令注意事項
在寫指令碼的時候, 一定要慎用 rm, 不確定時可以用 mv 命令, 移動到別的地方
# 危險指令, 當 var1 為空時
var1='某個指令執行的結果'
rm -f /$var1
完整的示例
#!/bin/sh
# 獲取本機 iplocal_ip(){
local_ip=`ip add | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | cut -d'/' -f 1 | head -n 1`
#echo ">> 獲取本機IP 為: $local_ip"
echo $local_ip
}
## java env
# export JAVA_HOME=/usr/local/jdk/jdk1.8.0_101
export JRE_HOME=$JAVA_HOME/jre
# extend lib path
libpath=sanritoolslib
# 本機 ipip=$(local_ip)
# Java opts
JAVA_OPTS="-Xms256m -Xmx256m -Dcom.sun.management.jmxremote.port=10086 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=$ip"
echo "JAVA_OPTS:${JAVA_OPTS}"
API_NAME=sanritools
JAR_NAME=$API_NAME\.jar
#PID 代表是PID檔案
PID=$API_NAME\.pid
#使用說明,用來提示輸入引數
usage() {
echo "Usage: sh server.sh [start|stop|restart|status]"
exit 1
}
#檢查程式是否在執行
is_exist(){
pid=`ps -ef|grep $JAR_NAME|grep -v grep|awk '{print $2}' `
#如果不存在返回1,存在返回0
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
#啟動方法
start(){
is_exist
if [ $? -eq "0" ]; then
echo ">>> ${JAR_NAME} is already running PID=${pid} <<<" else
nohup $JRE_HOME/bin/java -Dloader.path=$libpath $JAVA_OPTS -jar $JAR_NAME >/dev/null 2>&1 &
echo $! > $PID
echo ">>> start $JAR_NAME successed PID=$! <<<" fi
}
#停止方法
stop(){
#is_exist
pidf=$(cat $PID)
#echo "$pidf"
echo ">>> api PID = $pidf begin kill $pidf <<<" kill $pidf
rm -rf $PID
sleep 2
is_exist
if [ $? -eq "0" ]; then
echo ">>> api 2 PID = $pid begin kill -9 $pid <<<" kill -9 $pid
sleep 2
echo ">>> $JAR_NAME process stopped <<<" else
echo ">>> ${JAR_NAME} is not running <<<" fi
}
#輸出執行狀態
status(){
is_exist
if [ $? -eq "0" ]; then
echo ">>> ${JAR_NAME} is running PID is ${pid} <<<" else
echo ">>> ${JAR_NAME} is not running <<<" fi
}
#重啟
restart(){
stop
start}
#根據輸入引數,選擇執行對應方法,不輸入則執行使用說明
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
"*")
usage
;;
esac
exit 0