jenkins遠端部署使用shell指令碼進行備份與find和grep匹配的區別
需求
公司想jenkins在遠端部署專案的同時,還要進行專案備份,
之前只備份最近一次構建的資料,也就是隻保留到一份,
現在公司希望能保留按時間進行倒序,保留三份備份包。
思路
1、使用rm -rf 檔名
把我們要保留的三份備份包排除掉。
2、要排除查詢到的檔案,可以使用grep -v
命令。排除多少個可以使用head -n 3
rm -rf `ls | grep "ggservice-dataservice-.*" | grep -v `find . -name "ggservice-dataservice-*" | xargs ls -t | head -n 3|xargs|sed "s/.\///g" |xargs|sed "s/ /\\\\\\|/g"``
這麼一條命令太長了。我們使用變數的方式:
# 打包的檔名
fileName="ggservice-dataservice"
backup=`find . -name "${fileName}-*" | xargs ls -t | head -n 3|xargs|sed "s/.\///g"|xargs|sed "s/ /\\\\\\|/g"`
echo "保留最近三個備份包:" \"$backup\"
echo "刪除的備份包:"`ls | grep "${fileName}-.*" | grep -v $backup`
#刪除ggservice的備份包
rm -rf `ls | grep " ${fileName}-.*" | grep -v $backup`
1、我們先查詢出需要保留的三個備份包。
backup=`find . -name "${fileName}-*" | xargs ls -t | head -n 3|xargs|sed "s/.\///g"|xargs|sed "s/ /\\\\\\|/g"`
①首先find命令去模糊查詢檔名為ggservice-dataservice-*
。
find和grep匹配的區別
以我自己例子;查詢結果為:
./ggservice-dataservice-20161210
./ggservice-dataservice-20161211
./ggservice-dataservice-20161209
./ggservice-dataservice-20161202
./ggservice-dataservice-20161212
看到這個我們肯定希望把它們拼成如下形式:
ggservice-dataservice-20161212\|ggservice-dataservice-20161211\|ggservice-dataservice-20161202
為什麼要拼成這種實現呢?
我們要知道grep -v
同時排除多個檔案的方法是這樣的!
grep -v 'aaaa\|bbbb'
也就是說當有多個檔案時,需要 |
,進行分割,但是在Linux
中|
是管道的意思,
所以需要使用反斜槓進行轉義;所以是\|
。
②xargs ls -t
是進行按日期排序(倒序)。
③head -n 3
取前三個。
④xargs|sed "s/.\///g"
把查詢檔案結果中 ./
去除掉。
sed是 正則 替換 格式:s/填寫需要替換字元/填寫需要替換成什麼字元/g
s/被替換字元1/替換字元/g
⑤xargs|sed "s/ /\\\\\|/g"
把查詢檔案結果中的空格替換成|
。
這裡說明下⑤,在命令列中寫成三個反斜槓即xargs|sed "s/ /\\\|/g"
,但是寫到shell裡,或是賦值給一個變數時,會把反斜槓弄沒了:
ggservice-dataservice-20161212|ggservice-dataservice-20161211|ggservice-dataservice-20161202
後來經過我不斷嘗試,連續五個反斜槓就可以啦!即便是賦值給變數也是可以的。
最後backup
變數得到的就是:
ggservice-dataservice-20161212\|ggservice-dataservice-20161211\|ggservice-dataservice-20161202
有了這個後,我們就可以開始刪除了。
#刪除ggservice的備份包
rm -rf `ls | grep "^${fileName}-.*" | grep -v $backup`
①rm -rf 檔名
,由於檔名是通過命令來查詢出來的。所以需要使用`符號包裹起來,
grep “^${fileName}-.”
也就是鍵盤數字1左邊的那個鍵。
②這裡面的
.是正則表示式,匹配查詢到相應格式的檔案。
^
這裡新增這個符號表示的是以指定字元開頭進行匹配。
grep -v $backup`這裡是排除掉我需要備份的檔案。即不刪除它們,其餘匹配查詢到的檔案都進行刪除。
③
至此,我的需求已經達到要求了。
下面是我自己寫的完整指令碼:
#!/bin/bash
export PATH=~/gogoal_platform/ggopenapi:~/play-1.2.7:$PATH
echo "構建後的路徑pwd:"`pwd`
whoami
cd /home/developer/gogoal_platform/ggopenapi/
cur=$(pwd)
currday=`date +%Y%m%d`
# 打包的檔名
fileName="api"
#建立最新的備份包
gogalwebfile=${cur}/${fileName}-$currday
if [ ! -d $gogalwebfile ]; then
echo "不存在":$gogalwebfile
cp -r ${fileName} ${fileName}-$currday
fi
backup=`ls -lt | find . -name "${fileName}-*" | sort -r | head -n 3|xargs|sed "s/.\///g"|xargs|sed "s/ /\\\\\\|/g"`
echo "保留最近三個備份包:" \"$backup\"
echo "刪除的備份包:"`ls | grep "^${fileName}-.*" | grep -v $backup`
# 刪除備份包
rm -rf `ls | grep "^${fileName}-.*" | grep -v $backup | xargs | sed "s/ / /g"`
# 將分批打包的jar拷貝到ggservice專案中
cp -r package/* /home/developer/gogoal_platform/ggopenapi/api/ggservice/
rm -rf package
cd /home/developer/gogoal_platform/ggopenapi/api/ggservice/
cp /dev/null nohup.out
nohup ./ggservice.sh
更新
注:
2017-2-15修改:
1、
backup=`ls -lt | find . -name "${fileName}-*" | sort -r | head -n 3|xargs|sed "s/.\///g"|xargs|sed "s/ /\\\\\\|/g"`
添加了sort -r
,因為在使用ls -lt
排序後,再使用find
命令,會導致之前排好的順序變成無須,所以再使用sort
命令在排序一次,sort預設是升序,所以我們要進行新增引數-r
,進行取反。
2、由於我打包的是.class
檔案,命令如下:
#!/bin/bash
export PATH=~/play-1.2.7:$PATH
#獲得當前目錄
cur=$(pwd)
echo "pwd:"${cur}
rm -rf ggservice-dataservice.jar
output_path=${cur}/classes
package=${cur}/package
echo $output_path
if [ ! -d $output_path ]; then
mkdir $output_path
fi
if [ ! -d $package ]; then
mkdir $package
fi
## 獲取依賴庫和需要編譯的java檔案
export libs=`find ./dataservice/lib -name "*.jar" |xargs|sed "s/ /:/g"`
export javafiles=`find ./dataservice/ -name "*.java" |xargs|sed "s/ / /g"`
export javautils=`find ./utils/app/ -name "*.java" |xargs|sed "s/ / /g"`
export play_lib=/opt/play-1.2.7/framework/play-1.2.7.jar
export play_lib_common=`find /opt/play-1.2.7/framework/lib/ -name "*.jar" |xargs|sed "s/ /:/g"`
#echo ${javafiles}
#echo "公共---------"
#echo ${javautils}
# 清除
rm -rf package/*
# 清除編譯後的class檔案
rm -rf ${output_path}/*
##編譯
javac -d ${cur}/classes -cp ${libs}:$play_lib:$play_lib_common -encoding utf-8 ${javafiles} ${javautils}
##打包
cd /home/jenkins/workspace/ggservice/dataservice/app/ggservice/v1/
dir=$(ls -l |awk '/^d/ {print $NF}')
cd $output_path
for i in $dir
do
echo "ggservice-"${i}".jar打包情況":
jar -cvf ${package}/ggservice-${i}.jar */v1/$i/*
done
每次打jar
包的時候,最好先清除class檔案,今天就這個原因導致浪費很多時間。
# 清除編譯後的class檔案
rm -rf ${output_path}/*
2017-6-22修改:
今天偶然發現執行上面的指令碼居然把不想刪除的檔案給刪除啦!
結果呢?其把ggopenapi-mongo3
這個檔案也刪除啦!
看了看我的指令碼:
echo "刪除的備份包:"`ls | grep "${fileName}-.*" | grep -v $backup`
由於grep
是正則匹配,所以只要包含指定的字元就匹配成功,所以呢,我們需要加上^
。
echo "刪除的備份包:"`ls | grep "^${fileName}-.*" | grep -v $backup`