小白對jenkins運維的使用有點簡單的想法,這裏開個記錄貼記錄下。html
因爲未找到jenkins構建失敗後執行其餘腳本的插件,也暫時沒有使用其餘運維工具。因此想本身寫一個shell腳本,一是方便其餘人使用,二是能夠失敗後回滾。前端
本文使用gitlab webhook觸發jenkins構建,jenkins執行shell命令---》mvn或者npm打包---》打包成docker鏡像---》發佈---》發佈成功後用jenkins的git publisher插件push一個gitlab tag做爲備份。vue
若是構建失敗,則checkout最新的tag代碼---》從新打包---》打包成docker鏡像---》發佈運行。java
最後發現,結果是能夠正常構建,構建失敗也能夠回滾。可是jenkins的發佈狀態一直是success,沒法知道是正常構建仍是回滾構建成功。mysql
也想過,回滾的時候發佈郵件或者短信提醒。或者修改jenkins源碼,增長構建狀態roolback。linux
也想用這個shell腳本作個簡單的jenkins------easy-cigit
經過java調用linux命令,寫幾個前端頁面。頁面上填寫shell腳本的參數,點擊發布,查看日誌,查看容器,中止容器,重啓容器等操做。github
可是gitlab的webhook如何觸發java自動構建是個問題。web
後來發現有個gitlab runner能夠觸發命令,後期能夠研究下。spring
此處先貼出shell腳本:清除舊的構建、構建、回滾。
#鏡像名稱 IMAGE_NAME=$1 #容器名稱 CONTAINER_NAME=$2 #端口映射(9500:9000) PORT=$3 #語言類型(java or vue) LANG=$4 #日誌路徑夾 logs_path="logs/" #日誌名稱 log_name=$5 #日誌路徑 log_path=$logs_path$log_name function deploy(){ echo "=======================刪除舊容器=======================" t=`sudo docker ps -a | grep $1|awk '{print $1}'|sed 's/%//g'`; if [ $t ]; then sudo docker stop $t echo "中止容器成功" sudo docker rm $t echo "刪除容器成功" fi echo "=======================刪除無用鏡像=======================" docker images|grep none|awk '{print $3}'|xargs docker rmi echo "=================刪除多餘tag,保留最新三個================" tagnum=`git tag | wc -l`; tag=(`git tag`) a=0; echo "當前tag數目爲:" $tagnum "個" until [ $tagnum -lt 3 ] do echo $a 準備刪除tag:${tag[$a]} git tag -d ${tag[$a]} echo "=======================本地刪除成功=======================" git push $2 :refs/tags/${tag[$a]} echo "=======================遠程刪除成功=======================" a=`expr $a + 1` tagnum=`expr $tagnum - 1` done } function build(){ if [ $1 = java ];then echo "=======================jar包打包開始=======================" mvn package -DskipTests echo "=======================jar包打包完成=======================" echo "====================docker鏡像打包開始"====================" mvn dockerfile:build echo "====================docker鏡像打包完成"====================" else echo "=======================vue打包開始=======================" sudo /usr/local/bin/npm install sudo /usr/local/bin/npm run build echo "=======================vue打包完成=======================" echo "====================docker鏡像打包開始"====================" sudo docker build -t $2 . echo "====================docker鏡像打包完成"====================" fi echo '=================開始推送鏡像到docker私服==================' sudo docker push $2 echo '========================推送鏡像完成=======================' echo '=======================刪除舊的構建========================' # deploy $2 $4 >> $5 2>&1 echo '======================舊的構建刪除成功====================' echo '=======================容器運行開始========================' sudo docker run -d --name $4 -p:$3 $2 sudo docker ps | grep $2 echo '=======================容器運行完成========================' #port=($3//:/ ) #echo 訪問路徑爲:`ifconfig ens192 | grep "inet" | awk '{ print $2}' | awk -F: '{print $1}' | grep 192`:${port[0]} } function rollback(){ echo "====================================開始執行回滾====================================" echo '=======================刪除舊的構建========================' deploy $2 $4 >> $5 2>&1 echo '======================舊的構建刪除成功====================' tag=(`git tag`) echo "檢測到的git tag版本爲:" ${tag[*]} maxtag=(${tag[0]//_/ }) maxnum=${maxtag[1]} for i in ${!tag[*]};do nexttag=(${tag[$i]//_/ }) nextnum=${nexttag[1]} if [[ $maxnum -lt $nextnum ]];then maxnum=$nextnum fi done echo "檢測到最新的git tag版本爲:" rc_$maxnum echo "拉取上一次構建成功的tag代碼" if [ `git checkout rc_$maxnum` ];then echo "拉取代碼失敗,請手動選擇代碼構建" else echo "拉取代碼成功" fi build $1 $2 $3 $4 } mkdir logs echo '建立日誌文件成功' >> $log_path 2>&1 echo `date` >> $log_path 2>&1 echo "開始構建" >> $log_path 2>&1 build $LANG $IMAGE_NAME $PORT $CONTAINER_NAME $log_path >> $log_path 2>&1 resule=`sudo docker ps | grep pig-ui|awk '{print $1}'|sed 's/%//g'` if [ $resule != '' ];then echo "構建成功" else echo "回滾" rollback $LANG $IMAGE_NAME $PORT $CONTAINER_NAME $log_path >> $log_path 2>&1 fi
昨天初步寫好了如下幾個腳本
jenkins.sh jenkins調用傳參 auto_build.sh 自動構建 auto_destroy.sh 清理舊的構建 auto_rollback.sh 自動回滾 sendmail.sh 構建成功或者回滾成功經過sendmail發送郵件附加構建日誌
如今依舊用的jenkins的git拉取代碼、git publisher推送tag、git webhook自動觸發構建。
在腳本中加入git clone git@url能夠解決git拉取代碼問題。 git tag **能夠解決推送tag問題。
可是如何調用gitlab的webhook,使提交代碼到gitlab,不依靠jenkins自動觸發構建是個問題?
能夠考慮gitlab的runner?不過這個使用也要寫一點代碼。
不知足我傻瓜式ci/cd的初衷,用戶只須要輸入幾個參數就ok。
這裏先貼上分離後的腳本。
#鏡像名稱 IMAGE_NAME=$1 #容器名稱 CONTAINER_NAME=$2 #端口映射(9500:9000) PORT_MAPPING=$3 #語言類型(java or vue) PROJECT_LANG=$4 #日誌名稱 LOG_NAME=$5 #日誌路徑 LOG_PATH=logs/$LOG_NAME #收件郵箱 TO_LIST=$6 #是否回滾成功 IS_ROLLBACK=0 mkdir logs/ echo '建立日誌文件成功' >> $LOG_PATH bash /home/jenkins/auto_build.sh $PROJECT_LANG $IMAGE_NAME $PORT_MAPPING $CONTAINER_NAME $LOG_PATH $IS_ROLLBACK $TO_LIST $LOG_NAME | tee ./$LOG_PATH
1:PROJECT_LANG 判斷項目的語言,這裏只作了java和vue的判斷,分別執行各自語言的打包和bulid docker鏡像
2:IMAGE_NAME 鏡像名稱,用於docker打包時指定生成image的名稱,由於這裏我使用了docker私服,全部加入了docker push 操做。 鏡像名稱也用於後續的docker ps | grep **查找容器、刪除容器等等操做
3:PORT_MAPPING 端口映射,用戶指定docker run 時的-p 端口映射。也用於構建成功時經過(//:/ )等操做提取宿主機端口,生成服務的訪問url
4:CONTAINER_NAME 容器名稱,docker run --name指定的容器名稱,也用於後續的git push CONTAINER_NAME :refs/tags/rc_**遠程刪除tag,這裏通常取值爲gitlab中項目的名稱。
5:LOG_PATH 日誌的路徑。用於sendmail時附帶日誌
6:IS_ROLLBACK 是否回滾:jenkins.sh調用時爲0表示正常構建,rollback調用時爲1表示回滾構建。以此判斷髮送郵件的標題。
7:TO_LIST 收件人郵箱,多個以「,」分割
8:LOG_NAME 日誌名稱,因爲這裏的日誌名稱我是在jenkins中傳遞的 rc_$BUILD_NUMBER ,$BUILD_NUMBER爲jenkins構建的當前次數。把次數分離開加入到郵件標題, ***項目第***次構建
9:| tee ./$LOG_PATH 經過管道和tee 實現控制檯輸出日誌的同時將日誌保存到日誌文件中。(這裏的控制檯輸出日誌指得是jenkins構建日誌,若是直接用>>重定向的話,jenkins構建日誌將不會顯示腳本的日誌輸出)。
#項目語言 PROJECT_LANG=$1 #鏡像名稱 IMAGE_NAME=$2 #端口映射 PORT_MAPPING=$3 #容器名稱 CONTAINER_NAME=$4 #日誌路徑 LOG_PATH=$5 #是否回滾成功 IS_ROLLBACK=$6 #收件郵箱 TO_LIST=$7 #日誌名稱 LOG_NAME=$8 #構建次數 NUMBER=(${LOG_NAME//_/ }) echo "`date`第${NUMBER[1]}次構建" echo '=======================刪除舊的構建========================' bash /home/jenkins/auto_destroy.sh $IMAGE_NAME $CONTAINER_NAME echo '=========================刪除成功==========================' if [[ $PROJECT_LANG = java ]];then echo '=======================jar包打包開始=======================' mvn package -DskipTests if [[ `echo $?` -eq 0 ]];then echo '=======================jar包打包完成=======================' else echo '=======================jar包打包失敗=======================' bash /home/jenkins/auto_rollback.sh $PROJECT_LANG $IMAGE_NAME $PORT_MAPPING $CONTAINER_NAME $LOG_PATH $IS_ROLLBACK $TO_LIST $LOG_NAME exit 0 fi echo '=======================docker打包開始=======================' mvn dockerfile:build if [[ `echo $?` -eq 0 ]];then echo '=======================docker打包完成=======================' else echo '=======================docker打包失敗=======================' bash /home/jenkins/auto_rollback.sh $PROJECT_LANG $IMAGE_NAME $PORT_MAPPING $CONTAINER_NAME $LOG_PATH $IS_ROLLBACK $TO_LIST $LOG_NAME exit 0 fi else echo '=======================vue環境安裝開始=======================' sudo /usr/local/bin/npm install if [[ `echo $?` -eq 0 ]];then echo '=======================vue環境安裝完成=======================' else echo '=======================vue環境安裝失敗=======================' bash /home/jenkins/auto_rollback.sh $PROJECT_LANG $IMAGE_NAME $PORT_MAPPING $CONTAINER_NAME $LOG_PATH $IS_ROLLBACK $TO_LIST $LOG_NAME exit 0 fi echo '=======================vue打包開始=======================' sudo /usr/local/bin/npm run build if [[ `echo $?` -eq 0 ]];then echo '=======================vue打包完成=======================' else echo '=======================vue打包失敗=======================' bash /home/jenkins/auto_rollback.sh $PROJECT_LANG $IMAGE_NAME $PORT_MAPPING $CONTAINER_NAME $LOG_PATH $IS_ROLLBACK $TO_LIST $LOG_NAME exit 0 fi echo '=======================docker打包開始=======================' sudo docker build -t $2 . if [[ `echo $?` -eq 0 ]];then echo '=======================docker打包完成=======================' else echo '=======================docker打包失敗=======================' bash /home/jenkins/auto_rollback.sh $PROJECT_LANG $IMAGE_NAME $PORT_MAPPING $CONTAINER_NAME $LOG_PATH $IS_ROLLBACK $TO_LIST $LOG_NAME exit 0 fi fi echo '=======================容器運行開始========================' sudo docker run -d --name $CONTAINER_NAME -p:$PORT_MAPPING $IMAGE_NAME if [[ `echo $?` -eq 0 ]];then resule=`sudo docker ps | grep $IMAGE_NAME|awk '{print $1}'|sed 's/%//g'` if [[ $resule != '' ]];then sudo docker ps | grep $IMAGE_NAME echo '=======================容器運行完成========================' echo '=================開始推送鏡像到docker私服==================' sudo docker push $IMAGE_NAME echo '========================推送鏡像完成=======================' port=(${PORT_MAPPING//:/ }) echo 訪問路徑爲:http://`ifconfig ens192 | grep "inet" | awk '{ print $2}' | awk -F: '{print $1}' | grep 192`:${port[0]} if [[ $IS_ROLLBACK -eq 0 ]];then echo "構建成功" bash /home/jenkins/sendmail.sh $TO_LIST 成功:$CONTAINER_NAME第${NUMBER[1]}次構建 $LOG_PATH exit 0 else echo "回滾成功" bash /home/jenkins/sendmail.sh $TO_LIST 回滾:$CONTAINER_NAME第${NUMBER[1]}次構建 $LOG_PATH exit 0 fi exit 0 else echo "執行回滾" bash /home/jenkins/auto_rollback.sh $PROJECT_LANG $IMAGE_NAME $PORT_MAPPING $CONTAINER_NAME $LOG_PATH $IS_ROLLBACK $TO_LIST $LOG_NAME exit 0 fi exit 0 else echo "執行回滾" bash /home/jenkins/auto_rollback.sh $PROJECT_LANG $IMAGE_NAME $PORT_MAPPING $CONTAINER_NAME $LOG_PATH $IS_ROLLBACK $TO_LIST $LOG_NAME exit 0 fi exit 0
用於執行構建過程,清理舊的構建,以及構建失敗時調用回滾、發送構建郵件
#鏡像名稱 IMAGE_NAME=$1 #容器名稱 CONTAINER_NAME=$2 echo "=======================刪除舊容器=======================" t=`sudo docker ps -a | grep $IMAGE_NAME|awk '{print $1}'|sed 's/%//g'`; if [[ $t ]]; then sudo docker stop $t echo "中止容器成功" sudo docker rm $t echo "刪除容器成功" fi echo "=======================刪除無用鏡像=======================" docker images|grep none|awk '{print $3}'|xargs docker rmi echo "=================刪除多餘tag,保留最新三個================" tagnum=`git tag | wc -l`; tag=(`git tag`) a=0 echo "當前tag數目爲:" $tagnum "個" until [[ $tagnum -lt 3 ]] do echo $a 準備刪除tag:${tag[$a]} git tag -d ${tag[$a]} echo "=======================本地刪除成功=======================" git push $CONTAINER_NAME :refs/tags/${tag[$a]} echo "=======================遠程刪除成功=======================" a=`expr $a + 1` tagnum=`expr $tagnum - 1` done exit 0
用於清除沒有tag的鏡像、刪除舊的容器、刪除多餘的tag
#項目語言 PROJECT_LANG=$1 #鏡像名稱 IMAGE_NAME=$2 #端口映射 PORT_MAPPING=$3 #容器名稱 CONTAINER_NAME=$4 #日誌路徑 LOG_PATH=$5 #是否回滾成功 IS_ROLLBACK=1 #收件郵箱 TO_LIST=$7 #日誌名稱 LOG_NAME=$8 #構建次數 NUMBER=(${LOG_NAME//_/ }) echo "=======================開始執行回滾========================" echo '=======================刪除舊的構建========================' bash /home/jenkins/auto_destroy.sh $IMAGE_NAME $CONTAINER_NAME echo '======================舊的構建刪除成功====================' tag=(`git tag`) echo "檢測到的git tag版本爲:" ${tag[*]} maxtag=(${tag[0]//_/ }) maxnum=${maxtag[1]} for i in ${!tag[*]};do nexttag=(${tag[$i]//_/ }) nextnum=${nexttag[1]} if [[ $maxnum -lt $nextnum ]];then maxnum=$nextnum fi done echo "檢測到最新的git tag版本爲:" rc_$maxnum echo "拉取上一次構建成功的tag代碼" if [[ `git checkout rc_$maxnum` ]];then echo "拉取代碼失敗,請手動選擇代碼構建" else echo "拉取代碼成功" bash /home/jenkins/auto_build.sh $PROJECT_LANG $IMAGE_NAME $PORT_MAPPING $CONTAINER_NAME $LOG_PATH $IS_ROLLBACK $TO_LIST $LOG_NAME exit 0 fi exit 0
正常構建失敗後,拉取最新的tag分支代碼。從新執行構建。
#收件郵箱列表 TO_LIST=$1 #郵件標題 MAIL_TITLE=$2 #附件地址 LOG_PATH=$3 fromAdd="=?UTF-8?B?`echo $MAIL_TITLE | base64`?=" tolist="$TO_LIST" cclist="" subject="=?UTF-8?B?`echo $MAIL_TITLE | base64`?=" attach="$LOG_PATH" data=`cat $attach` ( echo "From: $fromAdd" echo "To: $tolist" echo "Cc: $cclist" echo "Subject: $subject" echo "MIME-Version: 1.0" echo 'Content-Type: multipart/mixed; boundary="GvXjxJ+pjyke8COw"' #echo "Content-Disposition: inline" echo echo "--GvXjxJ+pjyke8COw" echo "Content-Type: text/html; charset=US-ASCII" echo "Content-Disposition: inline" echo echo "<h1>Please check the attachment log.</h1>" echo echo "--GvXjxJ+pjyke8COw" echo "Content-Type: text/plain; charset=US-ASCII;" echo "Content-Disposition: attachment;filename="build.log"" echo echo "$data" echo echo "--GvXjxJ+pjyke8COw" ) | /usr/lib/sendmail -t
用於發送郵件
jenkins執行shell腳本:bash /home/jenkins/jenkins.sh IMAGE_NAME CONTAINER_NAME PORT_MAPPING PROJECT_LANG LOG_NAME TO_LIST
這裏能夠不用jenkins的Editable Email Notification插件
見https://www.cnblogs.com/jxd283465/p/11703557.html
EasyCi系統開發的目的是免去遠程發佈的免密登錄、拉取gitlab代碼的認證、手動添加gitlab hook、查看gitlab中該項目的git地址等等多餘的操做。這些操做均有後臺自動完成,系統提供運行環境一鍵安裝腳本、自動化安裝部署本系統、開箱即用,只須要幾個參數便可實現項目的遠程構建,暫時只支持vue和java項目的構建。
Easyci系統採用B/S架構,後端採用springboot框架、前端採用Vue的element ui、數據庫採用mysql、運行工具爲shell腳本、採用websocket進行實時日誌傳輸。
因爲系統由本人獨立開發,對前端開發不是很擅長,頁面比較簡單,只爲實現基本功能,後續會對功能和頁面進行優化。
EasyCI:easyci系統後臺,調用shell腳本、經過接口將結果返回前端
EasyCI-UI:easyci系統前臺,vue。調用後臺接口展現數據
Gitlab:代碼託管工具,經過gitlab hook觸發easyci持續集成交付
shell腳本:linux腳本
Docker私服:私有docker鏡像倉庫,用於遠程構建
MySQL:easyci系統數據庫
1.根據安裝文檔安裝系統,啓動系統
2.訪問系統首先須要驗證gitlab:gitlab的url、用戶名和密碼。用於選擇項目構建、服務器拉取代碼驗證、自動添加hook,免去手動操做。
3.添加遠程發佈服務器:服務器ip、端口、用戶名、密碼。後臺自動完成服務器間的免密登陸,用於項目遠程發佈、查看服務器容器以及容器的各類操做。
4.部署:選擇項目url、輸入docker容器端口映射關係、選擇項目類型、輸入收件人郵箱、選擇部署服務器,只須要輸入兩項內容便可完成部署。
5.點擊部署,會彈出窗口顯示系統部署日誌。
6.部署會自動添加easyci的hook接口url到該部署項目的hook中,用於自動觸發構建。
7.部署完成自動發送郵件給收件人郵箱,顯示構建結果、構建時間、構建項目、構建日誌。
8.後續開發人員提交代碼到該項目的gitlab,會觸發gitlab的hook調用easyci接口,查詢以前部署的信息進行自動部署,實現持續集成。
9.頁面展現easyci本機正在運行的容器和添加的遠程服務器正在運行的容器,支持數據自動刷新與關閉
10.能夠選擇添加的遠程服務器,查看該服務器的容器列表
11.容器操做:可點擊啓動 、中止、重啓、銷燬在頁面對服務器中運行的容器進行操做,即docker start|stop|restart|rm 容器名稱
12..容器實時日誌:點擊日誌,能夠查看該容器的實時日誌,即docker logs -f 容器名稱
https://www.cnblogs.com/jxd283465/p/11703557.html