1. 程式人生 > >jenkins遠端部署使用shell指令碼進行備份與find和grep匹配的區別

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 檔名,由於檔名是通過命令來查詢出來的。所以需要使用`符號包裹起來,
也就是鍵盤數字1左邊的那個鍵。
grep “^${fileName}-.這裡面的.是正則表示式,匹配查詢到相應格式的檔案。
這裡新增
^這個符號表示的是以指定字元開頭進行匹配。
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`