這個系列有四篇文章,自動部署分成了2篇:
- jenkins+git+maven持續集成(一):主要介紹Centos7下jenkins的安裝
- jenkins+git+maven持續集成(二):主要介紹下jenkins怎么集成git+maven進行自動構建
- jenkins+git+maven持續集成(三):主要介紹下jenkins怎么集成進行自動部署(發布到maven私有庫)
- jenkins+git+maven持續集成(四):主要介紹下jenkins怎么集成進行自動部署(通過SSH部署到服務器)
上一篇介紹了手動和自動發布包到maven私有庫,這篇主要介紹通過SSH進行自動部署。
再回到前面的jenkinsDemo任務編輯頁面,在構建的下面能看到“構建后操作”:
我們點開“增加構建后操作步驟”:
可以看到目前是沒有部署到linux服務器相關選項的。
部署到linux服務器上并運行
自動構建后還有一個用得更多的操作就是部署到對應的服務器上運行。在spring boot沒有廣泛運用之前,大多數java程序都是打成war部署到tomcat下運行;而spring boot一般則是通過內嵌tomcat打成個獨立的jar運行,如果有很多微服務的話可能會用到docker容器進行部署運行,不過那樣又會涉及到docker容器編排,不僅需要了解docker,還需要了解容器編排工具k8s之類的。
這里我們用spring boot打成jar包的方式來進行部署。
1. 安裝SSH插件
Jenkins默認是沒有SSH插件的,需要我們自己安裝。直接搜索SSH:
2. 通過SSH部署
找到“Publish Over SSH”進行安裝,完成后回到構建后操作:
選擇“Send build artifacts over SSH”:
在這個界面我們可以看到SSH Publishers下是SSH Server,下方有個“Add Server”;這說明我們可以一次構建部署到多個不同的SSH Server上。
然后SSH Server的構成是2部分,一個是Name,另一個是Transfers;而Transfer又是多個Transfer Set構成的。
Transfer Set上我們能看到“Source files”、“Remove prefix”、“Remote directory”和“Exec command”。從字面上就可以初步理解這些代表什么意思:
Source files:需要傳輸的文件
Remove prefix:去除前綴
Remote directory:需要傳輸文件到哪
Exec command:執行命令
從上到下,我們需要SSH Server的Name,這是個下拉框;很明顯我們目前沒有配置過,點開后面的提示:
需要我們在Jenkins的全局配置中進行:
點擊進去,直接到頁面最下方:
點擊新增一個SSH Server,直接點開每行后面的提示:
name:這里就是一個名字,根據公司要求來命名(最基本的要求是按環境來分)
Hostname:需要連接的主機域名或ip地址
Username:連接的用戶名
Remote Directory:這里是基礎的路徑,前面Transfer Set中的是在基礎路徑下的
默認能看到的就是這些信息,很明顯沒有驗證方式,我們點開高級:
可以看到有個認證方式的選擇框,最下方還有個測試配置的按鈕;選中復選框看有些什么:
發現一種是要輸入密碼的,一種是免密的方式;根據具體要求來定,我這里用密碼的方式。
測試下是否成功:
看到了Success,說明配置的這個SSH Server是成功的,保存后會到任務的編輯頁面。
可以看到SSH Server的Name直接是剛才配置的node2了,一般會配置多個,根據自己需要部署的具體Server選擇。
那么接下的Source files要怎么選擇呢,這是和構建的具體結構有關的。以我選擇的這個spring cloud工程為例,首先我需要做的是運行eureka工程下jar包,也就是啟動eureka的注冊中心。
我們來看下這個jar的位置,回到任務的主頁點開工作空間:
很明顯我們要的jar包不是在根目錄,其實這和我們本地執行maven構建是一樣的,eureka的jar包是在spring-cloud-eureka/target下:
所以Source files的地址在我們這個例子中就是:spring-cloud-eureka/target/*.jar
如果有多個的話就用逗號隔開。我們這里要的是jar包,所以jar包前面的那部分就是前綴prefix了:
剛才我們配置了一個基礎的Remote Directory路徑/usr/local/src/temp,我打算再建個eureka的文件夾,將jar放到/usr/local/src/temp/eureka下,那么這里就只需要加個eureka了:
看到提示說明如果沒有在公共配置Remote Directory,這里的就是直接路徑了。
接下就是我們需要執行什么命令了,注意連接后相當于用遠程工具連接一樣是在系統根目錄的,這里我們先只考慮第一次安裝,先進入對應的文件,直接運行jar了:
這里其實基本相當于你手動操作時在服務器上可以進行的操作,只是將命令放到jenkins中了。
到這里,配置基本結束了;我們先保存,點擊立即構建看是否能成功。
在控制臺我們能看到deploy到maven私有庫成功了,而且也運行到了我們配置的命令;給出的提示是java命令沒找到。在解決這個問題先下文件是否如我們期望地傳到了node2上:
可以看到已經成功了。(這里有個要注意的就是公共配置的Remote Directory路徑必須是存在的,我們這里配的是/usr/local/src/temp)
為什么java命令沒找呢,在node2上是可以直接運行的;是不是jenkins讀取不到node2上配置的環境變量呢。這里我們嘗試2種方式,一是寫全路徑:/usr/java/jdk1.8/bin/java -jar spring-cloud-eureka-1.0-SNAPSHOT.jar;
另一種是寫個shell腳本放在eureka下去運行:sh ./install.sh,腳本內容就是java -jar spring-cloud-eureka-1.0-SNAPSHOT.jar。
先看下第一種方式:
保存后運行:
在控制臺可以看到命令執行了,這里是eureka集群,控制臺中會有些錯誤信息;直接看最后的結果:
似乎Jenkins因為超時的原因強制關閉了連接;那么eureka啟動了沒有呢,我們檢查下:
正常啟動了。通過這個我們驗證了2點,Jenkins沒辦法找到服務器node2上環境變量,只能全路徑啟動;超過2分鐘會關閉連接。當然這種方式肯定不是我們需要的,首先我們沒必要寫全路徑,其次我們最后能讓這個程序在后臺運行不要在控制臺數據這么多信息。
那我們來看第二種方式,先創建好install.sh,并授權:
chmod 777 install.sh
修改編輯頁面命令為sh ./install.sh:
再啟動之前我們先強制kill掉剛才啟動的java進程:
保存后運行:
發現還是不行,難道只能寫全路徑了嗎?在網上找了個方案,在最前面加上:
source /etc/profile
這次和第一次一樣了,最后的結果也是一樣,說明直接在編輯界面用命令行和編輯界面運行shell效果是一樣的。這里最關鍵的地方是要運行source /etc/profile,這樣才能拿到需要部署服務器的環境變量。
這和我們期望的還是有一點差距,如果是自己跑demo基本上到這里就可以了;但是公司里運行的話這樣肯定不行,這是不穩定的構建。接下來我們進行改造,還是用第二種方式,在shell腳本中編寫;這樣的好處顯而易見,Jenkins的編輯界面這里只管調用shell腳本(shell腳本可以寫得很靈活,接收各種參數,這里就不擴展了)。
我們要達到的效果就是讓java -jar這個命令在后臺運行,這就是linux的知識了;本人對于linux只懂皮毛,百度了下個人覺得比較好的后臺運行方式:
nohup command > myout.file 2>&1 &
這是指定輸出文件:其中nohup將程序以忽略掛起信號的方式運行起來,末尾空格加&;如果不指定輸出文件,會掛起來要ctrl + c才能進入命令行。
還有一種方式,輸出到空(這里的/dev/null 是設備文件,不是普通文件,如果系統上沒有不要用普通創建文件的方式去執行,會導致系統不能連接。。。):
nohup command > /dev/null 2>&1 &
經過測試可以去掉nohup:
這樣就比較符合了,改造下shell腳本:
source /etc/profile
echo $JAVA_HOME
java -jar spring-cloud-eureka-1.0-SNAPSHOT.jar > myout.file 2>&1 &
kill掉java進程后再重新執行構建:
這樣就不會將日志輸出到控制臺阻塞住了,直接檢查下注冊中心頁面:
檢查下java進程:
啟動日志輸出文件:
SSH自動部署到服務器基本就完成了,當然實際項目中要考慮更多的問題:
比如啟動過了又要部署啟動怎么處理,首先要檢查端口是否被占用,如果占用了就kill掉再啟動;
還有就是怎么把shell腳本寫得更加靈活,支持多環境配置,多端口啟動等。
這些就不在這里擴展了,不過有了這些基本的知識可以避免不少坑;只需要再根據業務進行擴展和優化了。