jenkins 做爲一個自動化的集成工具,已是必不可少的了。它裏面提供各類插件,以及完備的基礎流程設施,爲你們的自動化集成之路提供了不少的方便。因此,咱們有必要完整的實踐一回。以切身體會到它的好處!前端
1. 下載jenkins包,並安裝;(兩種方案,基於物理機和基於docker,視狀況而定建議使用docker)java
2. 安裝後,初始化jenkins,基本都是下一步下一步搞定,保持默認是比較穩妥的選擇;node
3. 訂立目標,須要完成什麼的場景下的打包功能? git ? subversion? 或者其餘 ?git
4. 選擇此場景須要的必要插件安裝,並進行簡單調試;github
5. 新建一個任務,嘗試使用工具完成一次簡單的打包操做;web
6. 完善一個任務,使其能夠支持一些簡單的參數定製,如分支的選擇;docker
7. 打包完成後,編寫部署腳本,使其能夠一鍵部署;shell
8. 設置權限管理,使不一樣環境的包由不一樣級別的同窗進行操做;npm
9. 進行反覆功能驗證,及權限驗證;安全
10. 備註全部的操做流程,以便在進行下次從新安裝時,可以隨時搞定;
簡單的安裝和初始化,我們就很少說了,網上一大堆的信息,隨便找一個就能搞定,不找也能搞定,請參考官網: https://wiki.jenkins.io/display/JENKINS/Use+Jenkins
打包場景一: 如何打包 maven 管理的java項目 ?
其實要打包這種項目比較簡單,只要安裝一個 maven integeration 的插件便可!以下:
安裝好後,新建一個 maven 任務便可!
其實maven任務和其餘任務不太同樣的地方是,它會出現一個 pom.xml 的字樣,其實就是本身去加載這個配置文件,而後自行調用 maven 進行打包。而若是想要更靈活,也是能夠的,只須要使用 系統的命令進行自由構建便可!
goal 裏可寫: clean install | package
通過上面的操做後,你可能會發現,其實並不會打包成功,爲何呢?由於咱們尚未安裝 maven 的工具到系統上,或者說沒有向 jenkins 解釋 maven 在哪裏,因此須要到全局工具配置一下!
另外,若是你是須要打包 git 類的代碼的話,通常只須要進行簡單受權就能夠了!
到此,一個 簡單的 maven java 項目打包就成功了!
可是,其實,打包到這個程度,其實對咱們的環境部署一點更多的意義都沒有,因此咱們須要更深的定製化!我們稍後再說!
先來講說,另外一種項目的打包方式, h5 代碼的打包。 更具體的講,就是 基於 nodejs 的打包實現!
首先,咱們固然須要安裝 node js 的插件了!
一樣,該插件安裝好後,還要安裝 nodejs 的軟件!能夠直接選擇自動 安裝 ! 注意要求的版本!
安裝好後,新建一個自由風格的任務!
進入,把 node 的環境支持勾選上!而後定稿node 的打包命令!
一樣,git 相關的操做同樣!
至此,簡單的 node 版本的代碼打包功能也作好了。
一樣,只是進行打包,沒法定製化的東西,對咱們毫無心義,因此,咱們須要更高級的定製 jenkins !
例外:若是有依賴一些私有的包,那麼,你能夠選擇安裝私服,或者用以下方式解決:
# for local repository dependency... ln -sf /var/lib/jenkins/pkg-bak/testmodule/ $WORKSPACE/node_modules/testmodule npm install npm run prod
場景一: 我須要爲一個git 倉庫的多個分支打包?
這個,簡單, jenkins 中一添加定製化參數的功能,只須要添加一個文本參數就能夠 了!
在 git 分支一欄,寫入 $branch 替換便可!
如此,一個簡單的支持 git 多分支打包的功能就作好了!
可是:每次都讓我本身輸入分支,好煩啊! 並且,我本身也不必定知道有什麼樣的分支,這可怎麼辦?
藉助 groovy 腳本,能夠動態拉取 分支列表,進行顯示了!
簡單來講就是,執行一些shell腳本 , 從 git 遠端列舉出分支,給到列表選項! groovy 腳本以下:
def git_url = "https://github.com/yougewe/elastic-job-lite" def git_cmd = "/usr/local/git/bin/git ls-remote -h $git_url | grep -oP '(?<=refs/heads/).*' " branch = ['bash', '-c', git_cmd].execute().text.readLines()
好了,分支的選擇,看起來咱們已經解決得差很少了!
可是,前端有個點,就是這分支的觸發問題,其實咱們能夠更動態方式實現!
場景二: 我須要支持多個倉庫進行切換打包,固然這裏的倉庫將必然影響到上面分支列表的選擇!
可使用 Active Choice 這個插件,可讓咱們在須要的時候觸發一次分支的選擇,好比支持 分支快速過濾!達到數據聯動的效果;
而後,也可使分支依賴於動態的倉庫進行變動分支列表等等!總之, Active Choice 插件真是很方便發揮!
最終的效果就是,咱們能夠選擇,多倉庫,動態列表多分支,進行打包!
總之,經過這個聯動支持,以及簡單groovy知識,你能夠有很大的發揮空間;
場景三: 我須要將打好的包部署到指定服務器上?
這是個關鍵的問題,就是咱們打包來的包,應該處理的問題!
這裏有兩個核心問題: 1. 我如何找到打包後的東西? 2. 如何將找到的東西部署到線上?
若是不能很好的處理這些包,咱們將很無奈!因此 shell 就出場了!
jenkins 支持在打包後進行一些自定義的操做! 好比 上傳包到另外的服務器,或者部署到另外的地方等等!總之,就是任你發揮!
通常地說,查找打包後的東西,要依賴於你的代碼實現,因此具體問題具體分析;固然了,你能夠經過mvn等命令直接訂製打包的各類配置,從而活動查找的麻煩;
另外,對於部署到服務器,至少有兩個解決方案:1. 直接經過scp等服務器拷貝技術,將包放到目標服務器便可; 2. 將包打包成可執行的安裝包,上傳yum源服務器,在使用端直接拉取鏡像便可;
好比以下的腳本 ,咱們能夠將它部署到咱們指定服務器的 docker 容器中!
參考腳本以下:
echo "hello, build over ??? would you scp or deploy apps ??? work dir: $WORKSPACE , repository: $spec_repository;" # specify dev environment or product environment deploy_env_server="root@172.10.11.16" deploy_path_prefix="/opt/docker/webapps/test" docker_app_startup_script="/etc/init.d/startup restart"; case "$spec_repository" in richCash) docker_container_name="test_container"; docker_app_startup_script="/etc/init.d/startup restart"; deploy_path_prefix="/opt/docker/webapps/"; deploy_sub_path="$deploy_environment" case "$deploy_environment" in "test-p8081") docker_container_name="test_p8081_container" ;; docker_container_name="test_p8083_container" ;; *) # default container ;; esac deploy_path_prefix="/opt/docker/webapps/$deploy_sub_path"; ;; test2-01) deploy_path_prefix="/opt/docker/webapps/test2-01"; docker_container_name="test2_01_container"; docker_app_startup_script="/etc/init.d/startup restart"; ;; *) echo "not find special configures in $spec_repository, do the default thing"; ;; esac # deploy script deploy_script_path="ssh $deploy_env_server \"docker exec $docker_container_name bash -c '$docker_app_startup_script'\""; pom_file="$WORKSPACE/pom.xml"; pom_file_tmp="$pom_file\.tmp"; cd $WORKSPACE; cat $pom_file | awk '{if($0 ~ /<parent>/){parent_begin++; print "no dump parent"} else if(parent_begin > 0){ if($0 ~ /<\/parent>/){parent_begin = 0; print "match the parent end.";} else {print "hit parent dump"; }} else { print $0;}}' > $pom_file_tmp package_artifactId=`grep "<artifactId>" $pom_file_tmp | head -n 1 | sed -e 's/\(\s*<artifactId>\|<\/artifactId>\s*\)//g'`; package_version=`grep "<version>" $pom_file_tmp | head -n 1 | sed -e 's/\(\s*<version>\|<\/version>\s*\)//g'`; package_full_name="$package_artifactId-$package_version.jar" # 定義爲jar包寫死 package_full_path="$WORKSPACE/target/$package_full_name"; echo "packaged file is: $package_full_name"; scp $package_full_path $deploy_env_server:"$deploy_path_prefix/$package_full_name"; # restart the server... eval $deploy_script_path;
如上,是對 jar 包的部署方式,咱們再來看下 h5 包的部署方式:
echo "hello, build over ??? work dir: $WORKSPACE , repository: $spec_repository; branch: $branch ;" # specify dev environment or product environment deploy_env_server="root@172.11.1.12" docker_container_name="web_container"; deploy_path_prefix="/opt/docker/webapps/"; deploy_sub_path="$deploy_environment" deploy_path_prefix="$deploy_path_prefix""$deploy_sub_path" deploy_package_bak_path="/opt/docker/webapps/bak/" docker_app_startup_script="ls " case "$deploy_environment" in "web-p81") docker_container_name="web_81_container" ;; *) # default container ;; esac datetime=`date '+%Y%m%d%H%M'`; package_full_name="$spec_repository-$branch-$datetime.tar.gz" package_full_origin_path_prefix="/var/lib/jenkins/tmppackages/h5" package_full_origin_path="$package_full_origin_path_prefix/$package_full_name"; deploy_package_bak_path="$deploy_package_bak_path""$package_full_name" # deploy script deploy_script_path="ssh $deploy_env_server \"rm -rf $deploy_path_prefix/*; if [ ! -d $deploy_path_prefix ]; then mkdir -p $deploy_path_prefix; fi; tar -xzf $deploy_package_bak_path -C $deploy_path_prefix\""; package_dist_origin_path="$WORKSPACE/dist"; cd $package_dist_origin_path; tar -czf $package_full_origin_path -C $package_dist_origin_path .; echo "packaged file is: $package_full_origin_path"; scp $package_full_origin_path $deploy_env_server:"$deploy_package_bak_path"; # restart the server... eval $deploy_script_path;
如上,h5 的打包方式,區別在於須要手動打包一爲 gz 包,而後到目標機器進行解壓縮便是安裝!
如上,就能夠進行一鍵部署測試環境了!
剩下的,就是本身自由發揮了!
同理於 h5 的部署方式!
其實,準確來講,上面的操做都比較常規,由於都是最終的結果步驟展現!可是其實這其中有不少的坑,指望提示對你有幫助!
1. 使用groovy 進行分支獲取時, 須要對 git 命令進行免密受權操做,不然將永遠拉不到分支;
2. 使用scp, scp 這些命令調用遠程,須要免密登陸,不然受權失敗;
3. 使用 ssh xx@1.2.2.4 "ls ." 運行遠程命令如同本地命令;
4. 真正的部署腳本能夠遠程服務器上,也能夠寫在部署機器上;
5. 出於安全考慮,默認狀況下運行jenkins的用戶都不是root,因此通常不要覺得在terminal操做正常的命令,在jenkins上也能正常;
爲何必定要用jenkins?難道就由於其名聲大燥嗎?實際上是是由於它真的能帶來這些好處:
1. 部署速度指數級提高,之前按照我的的操做速度,要10分鐘左右的操做且要記憶多種複雜關聯命令,如今可能只要2分鐘一鍵搞定,爽不爽?
2. 部署信息有跡可查,若是按照以前的部署,誰部署出了問題,徹底不知道,可是jenkins上有操做記錄,更易發現問題;
3. 解決了系統兼容性問題引起的不適,以前各自部署來源不一致,可能致使各類難查問題,而用jenkins則保證徹底一致;
4. 拒毫不可靠錯誤代碼的上線,藉助於jenkins的單元測試功能,能夠發如今一些簡單代碼的問題,避免以前的誤操做上線;
5. 由於收口部署方式,對於後續新的部署方案,有了更加有利的支持,好比想加入sonar代碼掃描,只需修改下部署部署腳本便可;
一句話總結:有時知道問題比解決問題更重要!