本篇和大家分享的是springboot打包並結合shell指令碼命令部署,重點在分享一個shell程式啟動工具,希望能便利工作;
- profiles指定不同環境的配置
- maven-assembly-plugin打發布壓縮包
- 分享shenniu_publish.sh程式啟動工具
- linux上使用shenniu_publish.sh啟動程式
profiles指定不同環境的配置
通常一套程式分為了很多個部署環境:開發,測試,uat,線上 等,我們要想對這些環境區分配置檔案,可以通過兩種方式:
- 通過application.yml中編碼指定 profile.active=uat 方式指定
- 通過mvn中profiles來區分不同環境對應的配置資料夾,人工可以手動在idea勾選生成不同環境的包(推薦)
這裡我們要講的是第二種,首先在mvn中配置如下內容:
1 <profiles> 2 <profile> 3 <id>node</id> 4 <properties> 5 <!--傳遞給指令碼的引數值--> 6 <activeProfile>node</activeProfile> 7 <package-name>${scripts_packageName}</package-name> 8 <boot-main>${scripts_bootMain}</boot-main> 9 </properties> 10 <activation> 11 <activeByDefault>true</activeByDefault> 12 </activation> 13 </profile> 14 <profile> 15 <id>node1</id> 16 <properties> 17 <activeProfile>node1</activeProfile> 18 <package-name>${scripts_packageName}</package-name> 19 <boot-main>${scripts_bootMain}</boot-main> 20 </properties> 21 </profile> 22 <profile> 23 <id>node2</id> 24 <properties> 25 <activeProfile>node2</activeProfile> 26 <package-name>${scripts_packageName}</package-name> 27 <boot-main>${scripts_bootMain}</boot-main> 28 </properties> 29 </profile> 30 </profiles>
節點粗解:
- id:用來指定不同環境配置檔案所在的目錄,如下我這裡:
- properties:該節點中的節點是可作為引數傳遞給其他配置檔案,如我這裡的package-name節點值就可以在另外的assembly.xml或者shell指令碼檔案中通過${package-name}獲取到,如下:
- activeByDefault:指定預設環境配置資料夾
maven-assembly-plugin打發布壓縮包
對於springboot程式打包,可以分為jar和war,這裡是jar包;有場景是咋們配置檔案或者第三方等依賴包不想放到工程jar中,並且把這些檔案壓縮成一個zip包,方便上傳到linux;此時通過maven-assembly-plugin和maven-jar-plugin就可以做到,mvn的配置如:
1 <plugin> 2 <groupId>org.apache.maven.plugins</groupId> 3 <artifactId>maven-jar-plugin</artifactId> 4 <version>2.6</version> 5 <configuration> 6 <archive> 7 <addMavenDescriptor>false</addMavenDescriptor> 8 <manifest> 9 <addClasspath>true</addClasspath> 10 <classpathPrefix>lib/</classpathPrefix> 11 <mainClass>${scripts_bootMain}</mainClass> 12 </manifest> 13 </archive> 14 <!--打包排除項--> 15 <excludes> 16 <exclude>**/*.yml</exclude> 17 <exclude>**/*.properties</exclude> 18 <exclude>**/*.xml</exclude> 19 <exclude>**/*.sh</exclude> 20 </excludes> 21 </configuration> 22 <executions> 23 <execution> 24 <id>make-a-jar</id> 25 <phase>compile</phase> 26 <goals> 27 <goal>jar</goal> 28 </goals> 29 </execution> 30 </executions> 31 </plugin> 32 33 <plugin> 34 <groupId>org.apache.maven.plugins</groupId> 35 <artifactId>maven-assembly-plugin</artifactId> 36 <version>2.4</version> 37 <!-- The configuration of the plugin --> 38 <configuration> 39 <!-- Specifies the configuration file of the assembly plugin --> 40 <descriptors> 41 <descriptor>${project.basedir}/src/main/assembly/assembly.xml</descriptor> 42 </descriptors> 43 </configuration> 44 <executions> 45 <execution> 46 <id>make-assembly</id> 47 <phase>package</phase> 48 <goals> 49 <goal>single</goal> 50 </goals> 51 </execution> 52 </executions> 53 </plugin>
值得注意的地方如下幾點:
- mainClass節點:用來指定啟動main函式入口類路徑,如這裡的:com.sm.EurekaServerApplication
- excludes節點:排除主jar包中配置等一些列字尾檔案,因為我們要包這些配置檔案放到主包外面
- descriptor節點:用來指定assembly外掛對應的assembly.xml配置檔案
有了上面mvn配置,我們還需要assembly.xml的配置,這裡提取了結合shell指令碼釋出程式的配置:
1 <assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd 3 http://maven.apache.org/ASSEMBLY/2.0.0 "> 4 <id>${activeProfile}</id> 5 <!--打包成一個用於釋出的zip檔案--> 6 <formats> 7 <format>zip</format> 8 </formats> 9 <!--true:zip中生成一級目錄(此處遮蔽,配合指令碼需要profiles字尾)--> 10 <includeBaseDirectory>false</includeBaseDirectory> 11 <dependencySets> 12 <dependencySet> 13 <!--打包進zip檔案的lib目錄--> 14 <useProjectArtifact>false</useProjectArtifact> 15 <outputDirectory>${package-name}-${activeProfile}/lib</outputDirectory> 16 <unpack>false</unpack> 17 </dependencySet> 18 </dependencySets> 19 20 <fileSets> 21 <!-- 配置檔案打包進zip檔案的conf目錄 --> 22 <fileSet> 23 <directory>${project.basedir}/src/main/profiles/${activeProfile}</directory> 24 <outputDirectory>${package-name}-${activeProfile}/conf</outputDirectory> 25 <includes> 26 <include>**/*</include> 27 <!--<include>*.xml</include>--> 28 <!--<include>*.properties</include>--> 29 <!--<include>*.yml</include>--> 30 </includes> 31 </fileSet> 32 33 <!--啟動指令碼打包進zip檔案--> 34 <fileSet> 35 <directory>${project.basedir}/src/main/scripts</directory> 36 <outputDirectory></outputDirectory> 37 <includes> 38 <include>**/*</include> 39 </includes> 40 <!-- 檔案檔案許可權為777 --> 41 <fileMode>777</fileMode> 42 <!-- 目錄許可權為777 --> 43 <directoryMode>777</directoryMode> 44 <!--指令碼中引數變數為pom中的值 關鍵--> 45 <filtered>true</filtered> 46 </fileSet> 47 48 <!-- 專案編譯出來的jar打包進zip檔案 --> 49 <fileSet> 50 <directory>${project.build.directory}</directory> 51 <outputDirectory>${package-name}-${activeProfile}/</outputDirectory> 52 <includes> 53 <include>*.jar</include> 54 </includes> 55 </fileSet> 56 </fileSets> 57 </assembly>
重點節點介紹:
- formats節點:把配置檔案和jar包等壓縮成什麼檔案格式,這裡可以有:zip,tar等
- fileMode節點:指定scripts目錄下指令碼檔案(這裡是:shenniu_publish.sh)在linux上檔案許可權為777
- filtered節點:指令碼中引數變數為pom的profiles中properties的值(該配置,是把mvn中屬性值對映生成到sh檔案中,如:${package-name})
完成上面配置後,此時我們可以通過idea上勾選切換不同環境來打zip包,如圖:
分享shenniu_publish.sh程式啟動工具
上面步驟完成了zip格式的釋出包,我們再分享下啟動程式的shell指令碼,該指令碼具有的功能如:
- 解壓zip+啟動jar包
- 啟動jar包
- 停止對應jar執行
- 重啟jar程式
目前該shell中封裝了兩種啟動jar命令的方式:
- java -cp
- java -jar
如圖命令格式:
來看全部的shell程式碼:
1 #!/usr/bin/env bash 2 #可變引數變數 3 languageType="javac" #支援 java,javac,netcore 釋出 4 #引數值由pom檔案傳遞 5 baseZipName="${package-name}-${activeProfile}" #壓縮包名稱 publish-test.zip的publish 6 packageName="${package-name}" #命令啟動包名 xx.jar的xx 7 mainclass="${boot-main}" #java -cp啟動時,指定main入口類;命令:java -cp conf;lib\*.jar;${packageName}.jar ${mainclass} 8 9 #例子 10 # baseZipName="publish-test" #壓縮包名稱 publish-test.zip的publish 11 # packageName="publish" #命令啟動包名 publish.jar的xx 12 13 #固定變數 14 basePath=$(cd `dirname $0`/; pwd) 15 baseZipPath="${basePath}/${baseZipName}.zip" #壓縮包路徑 16 baseDirPath="${basePath}" #解壓部署磁碟路徑 17 pid= #程式pid 18 19 #解壓 20 function shenniu_unzip() 21 { 22 echo "解壓---------------------------------------------" 23 echo "壓縮包路徑:${baseZipPath}" 24 if [ ! `find ${baseZipPath}` ] 25 then 26 echo "不存在壓縮包:${baseZipPath}" 27 else 28 echo "解壓磁碟路徑:${baseDirPath}/${baseZipName}" 29 echo "開始解壓..." 30 31 #解壓命令 32 unzip -od ${baseDirPath}/${baseZipName} ${baseZipPath} 33 34 #設定執行許可權 35 chmod +x ${baseDirPath}/${baseZipName}/${packageName} 36 37 echo "解壓完成。" 38 fi 39 } 40 41 #檢測pid 42 function getPid() 43 { 44 echo "檢測狀態---------------------------------------------" 45 pid=`ps -ef | grep -n ${packageName} | grep -v grep | awk '{print $2}'` 46 if [ ${pid} ] 47 then 48 echo "執行pid:${pid}" 49 else 50 echo "未執行" 51 fi 52 } 53 54 #啟動程式 55 function start() 56 { 57 #啟動前,先停止之前的 58 stop 59 if [ ${pid} ] 60 then 61 echo "停止程式失敗,無法啟動" 62 else 63 echo "啟動程式---------------------------------------------" 64 65 #選擇語言型別 66 read -p "輸入程式型別(java,javac,netcore),下一步按Enter鍵(預設:${languageType}):" read_languageType 67 if [ ${read_languageType} ] 68 then 69 languageType=${read_languageType} 70 fi 71 echo "選擇程式型別:${languageType}" 72 73 #進入執行包目錄 74 cd ${baseDirPath}/${baseZipName} 75 76 #分類啟動 77 if [ "${languageType}" == "javac" ] 78 then 79 if [ ${mainclass} ] 80 then 81 nohup java -cp conf:lib\*.jar:${packageName}.jar ${mainclass} >${baseDirPath}/${packageName}.out 2>&1 & 82 #nohup java -cp conf:lib\*.jar:${packageName}.jar ${mainclass} >/dev/null 2>&1 & 83 fi 84 elif [ "${languageType}" == "java" ] 85 then 86 nohup java -jar ${baseDirPath}/${baseZipName}/${packageName}.jar >/dev/null 2>&1 & 87 # java -jar ${baseDirPath}/${baseZipName}/${packageName}.jar 88 elif [ "${languageType}" == "netcore" ] 89 then 90 #nohup dotnet run ${baseDirPath}/${baseZipName}/${packageName} >/dev/null 2>&1 & 91 nohup ${baseDirPath}/${baseZipName}/${packageName} >/dev/null 2>&1 & 92 fi 93 94 #查詢是否有啟動程式 95 getPid 96 if [ ${pid} ] 97 then 98 echo "已啟動" 99 #nohup日誌 100 tail -n 50 -f ${baseDirPath}/${packageName}.out 101 else 102 echo "啟動失敗" 103 fi 104 fi 105 } 106 107 #停止程式 108 function stop() 109 { 110 getPid 111 if [ ${pid} ] 112 then 113 echo "停止程式---------------------------------------------" 114 kill -9 ${pid} 115 116 getPid 117 if [ ${pid} ] 118 then 119 #stop 120 echo "停止失敗" 121 else 122 echo "停止成功" 123 fi 124 fi 125 } 126 127 #啟動時帶引數,根據引數執行 128 if [ ${#} -ge 1 ] 129 then 130 case ${1} in 131 "start") 132 start 133 ;; 134 "restart") 135 start 136 ;; 137 "stop") 138 stop 139 ;; 140 "unzip") 141 #執行解壓 142 shenniu_unzip 143 #執行啟動 144 start 145 ;; 146 *) 147 echo "${1}無任何操作" 148 ;; 149 esac 150 else 151 echo " 152 command如下命令: 153 unzip:解壓並啟動 154 start:啟動 155 stop:停止程式 156 restart:重啟 157 158 示例命令如:./shenniu_publish start 159 " 160 fi
正如上面小節說的,shell中的引數 package-name,activeProfile,boot-main 都是由mvn中profiles的properties中提供,是可變的引數,指令碼程式碼本身不需要人工去修改,只需要變的是mvn的引數即可;其實在我們生成zip包的時候,shell中的引數就被替換了,可以看zip中shell檔案內容如:
linux上使用shenniu_publish.sh啟動程式
把生成的zip上傳到linux上,通過命令解壓:
1 unzip -od eureka-server-0.0.1-node eureka-server-0.0.1-node.zip
其實shell指令碼中包含有解壓命令,但是我在打包時放在了zip中,所以只能通過手動解壓了,當然可以調整;此時進入加壓目錄如此:
注:這裡第一次執行./shenniu_publish.sh指令碼時候,提示了錯誤資訊;是由於我是在windows上編輯的這個指令碼,其空格等和linux上不一樣,所以執行會有問題,要解決可以使用vim命令在linux把該檔案轉成linux格式,如下命令:
1 vim shenniu_publish.sh 2 set ff=unix 3 :wq
執行完後,再來執行指令碼./shenniu_publish.sh,此時有如下提示:
此刻我們檔案是解壓狀態,因此只需要start命令啟動程式即可:
到這裡shenniu_publish.sh指令碼使用就完成了,只要指令碼沒有提示錯誤,基本都能啟動jar服務;其他restart和stop命令也如此執行就行:
可以去研究下shell程式碼,希望該指令碼能給你帶來效率和好的學習思路,下面是測試用例git地址,指令碼在eureka-server專案中:https://github.com/shenniubuxing3/springcloud-Finchley.SR2