├── .gitignore ├── README.md ├── api-deploy.sh ├── demo ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ └── DemoApplication.java │ └── resources │ │ ├── application-dev.properties │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── demo │ └── DemoApplicationTests.java ├── doc └── image │ ├── jenkins-config1.png │ ├── jenkins-config2.png │ ├── jenkins-config3.png │ └── jenkins-config4.png ├── pom.xml └── springboot-jenkins-deploy.sh /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # springboot-jenkins 2 | jenkins 构建、打包、远程部署springboot项目 3 | 4 | ## 远程部署(JAR包) 5 | 远程部署的目标服务器上,一般都会有一个shell部署脚本给jenkins远程调用,它所做的事情大致如下: 6 | 1、停止正在运行的服务(kill -9) 7 | 2、备份(xxx.jar.20170714125400) 8 | 3、删除发布目录中的jar文件 9 | 4、拷贝新的jar文件到发布目录中 10 | 5、启动项目 (java -jar) 11 | 6、监听启动日志(tail -f) 12 | 13 | 远程部署的目录结构: 14 | ``` 15 | --spring-boot-demo 16 | ----dev 17 | -------my-app.jar 18 | -------initServer.log 19 | 20 | ----test 21 | -------my-app.jar 22 | -------initServer.log 23 | 24 | ----prod 25 | -------my-app.jar 26 | -------initServer.log 27 | ``` 28 | 项目打包后的目录结构: 29 | ``` 30 | 分为两种,第一种是分离方式,第二种配置、lib都在一个jar包里; 31 | 第一种: 32 | --my-project 33 | ----bin 34 | -------startup.sh 35 | ----conf 36 | -------application.properties 37 | ----log 38 | -------app.log 39 | ----lib 40 | -------my-app.jar 41 | -------xxx.jar 42 | -------xxx.jar 43 | 第二种(本例子是这种): 44 | -------my-app.jar 45 | 46 | ``` 47 | jenkins 中设置 `Post Steps` Execute shell: 48 | ``` java 49 | scp $WORKSPACE/demo/target/demo*.jar smalldok@172.17.0.2:/home/smalldok/build/ 50 | BUILD_ID=dontKillMe ssh smalldok@172.17.0.2 "/home/smalldok/springboot-jenkins-deploy.sh -u 'remote://127.0.0.1:8001/demo?profile=dev&enable_debug=false&enable_jmx=false'" 51 | ``` 52 | springboot-jenkins-deploy.sh的传参采用URL方式(参考的dubbo url设计); 53 | URL中协议头、IP这两个参数暂时还没什么用,供以后扩展吧; 54 | 55 | ``` 56 | 目标服务器上,提前建好几个目录 57 | /home/smalldok/build 58 | /home/smalldok/backcup 59 | /home/smalldok/release 60 | ``` 61 | 62 | 部署shell脚本: 63 | springboot-jenkins-deploy.sh 64 | ``` java 65 | #!/bin/sh 66 | #local://127.0.0.1:8001/springboot-demo?profile=dev&enable_debug=false&enable_jmx=false 67 | #remote://127.0.0.1:8001/springboot-demo?profile=dev&enable_debug=false&enable_jmx=false 68 | 69 | protocol="" 70 | ip="" 71 | port="" 72 | context_path="" 73 | queryStr="" 74 | profile="dev" 75 | enable_debug="false" 76 | enable_jmx="false" 77 | function help() 78 | { 79 | cat < [$backupFile]" 224 | fi 225 | echo " " 226 | } 227 | function deleteFiles(){ 228 | echo "Deleting $destFile" 229 | rm -rf $destFile 230 | #echo "Deleting $destConfigFolder" 231 | #rm -rf $destConfigFolder 232 | echo "Deleting $dstLogFile" 233 | rm -rf $dstLogFile 234 | echo " " 235 | } 236 | 237 | function copyFiles(){ 238 | echo "Copying files from $sourFile" 239 | cp $sourFile $destFile 240 | #echo "Copying files from $sourConfigFolder" 241 | #cp -r $sourConfigFolder $destConfigFolder 242 | echo " " 243 | } 244 | 245 | JAVA_OPTS="" 246 | JAVA_MEM_OPTS="" 247 | JAVA_DEBUG_OPTS="" 248 | JAVA_JMX_OPTS="" 249 | function run(){ 250 | JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true" 251 | JAVA_MEM_OPTS="" 252 | BITS=`java -version 2>&1 | grep -i 64-bit` 253 | if [ -n "$BITS" ]; then 254 | JAVA_MEM_OPTS=" -server -Xmx1g -Xms1g -Xmn512m -XX:PermSize=512m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 " 255 | else 256 | JAVA_MEM_OPTS=" -server -Xms1g -Xmx2g -XX:PermSize=1024m -XX:SurvivorRatio=2 -XX:+UseParallelGC " 257 | fi 258 | JAVA_DEBUG_OPTS="" 259 | if [ "$enable_debug" = "true" ]; then 260 | JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=5566,server=y,suspend=n " 261 | fi 262 | JAVA_JMX_OPTS="" 263 | if [ "$enable_jmx" = "true" ]; then 264 | JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false " 265 | fi 266 | #echo "java -jar $destFile $properties" | at now + 1 minutes 267 | touch $dstLogFile | chmod 777 $dstLogFile 268 | nohup nice java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -jar $destFile $properties $> $dstLogFile 2>&1 & 269 | echo "COMMAND: nohup nice java -jar $destFile $properties $> $dstLogFile 2>&1 &" 270 | echo " " 271 | } 272 | function changeFilePermission(){ 273 | echo "Changing File Permission: chmod 777 $destFile" 274 | chmod 777 $destFile 275 | echo " " 276 | } 277 | 278 | function watch(){ 279 | tail -f $dstLogFile | 280 | while IFS= read line 281 | do 282 | echo "$msgBuffer" "$line" 283 | 284 | if [[ "$line" == *"$whatToFind"* ]]; then 285 | echo $msgAppStarted 286 | pkill tail 287 | fi 288 | done 289 | } 290 | 291 | ### FUNCTIONS CALLS 292 | ##################### 293 | # Use Example of this file. Args: enviroment | port | project name | external resourcce 294 | # BUILD_ID=dontKillMe /path/to/this/file/api-deploy.sh dev 8082 spring-boot application-localhost.yml 295 | 296 | # 1 - stop server on port ... 297 | stopServer 298 | backup 299 | # 2 - delete destinations folder content 300 | deleteFiles 301 | 302 | # 3 - copy files to deploy dir 303 | copyFiles 304 | 305 | changeFilePermission 306 | # 4 - start server 307 | run 308 | 309 | # 5 - watch loading messages until ($whatToFind) message is found 310 | watch 311 | ``` 312 | jenkins 配置截图 313 | ![General](doc/image/jenkins-config1.png) 314 | ![源码管理](doc/image/jenkins-config2.png) 315 | ![构建触发器](doc/image/jenkins-config3.png) 316 | ![Build 和 Post Steps](doc/image/jenkins-config4.png) 317 | 318 | 参考:https://github.com/rcoli/spring-boot-jenkins.git -------------------------------------------------------------------------------- /api-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # COMMAND LINE VARIABLES 4 | #enviroment FIRST ARGUMENT 5 | # Ex: dev | sit | uat 6 | env=$1 7 | # deploy port SECOND ARGUMENT 8 | # Ex: 8090 | 8091 | 8092 9 | serverPort=$2 10 | # THIRD ARGUMENT project name, deploy folder name and jar name 11 | projectName=$3 #spring-boot 12 | # FOURTH ARGUMENT external config file name 13 | # Ex: application-localhost.yml 14 | configFile=$4 15 | 16 | 17 | #### CONFIGURABLE VARIABLES ###### 18 | #destination absolute path. It must be pre created or you can 19 | # improve this script to create if not exists 20 | destAbsPath=/home/smalldok/release/$projectName/$env 21 | backupPath=/home/smalldok/backup 22 | #configFolder=resources 23 | ############################################################## 24 | 25 | ##### 26 | ##### DONT CHANGE HERE ############## 27 | #jar file 28 | # $WORKSPACE is a jenkins var 29 | #sourFile=$WORKSPACE/api/build/libs/$projectName*.jar 30 | sourFile=/home/smalldok/build/$projectName*.jar 31 | destFile=$destAbsPath/$projectName.jar 32 | 33 | #config files folder 34 | #sourConfigFolder=$WORKSPACE/$configFolder* 35 | #destConfigFolder=$destAbsPath/$configFolder 36 | 37 | #properties=--spring.config.location=$destAbsPath/$configFolder/$configFile 38 | properties="--server.port=$serverPort --spring.profiles.active=$env" 39 | 40 | #CONSTANTS 41 | logFile=initServer.log 42 | dstLogFile=$destAbsPath/$logFile 43 | #whatToFind="Started Application in" 44 | whatToFind="Started " 45 | msgLogFileCreated="$logFile created" 46 | msgBuffer="Buffering: " 47 | msgAppStarted="Application Started... exiting buffer!" 48 | 49 | ### FUNCTIONS 50 | ############## 51 | function stopServer(){ 52 | echo " " 53 | echo "Stoping process on port: $serverPort" 54 | pid=`ps -ef | grep $projectName.jar | grep -v grep | awk '{print $2}'` 55 | if [ -n "$pid" ] 56 | then 57 | kill -9 $pid 58 | fi 59 | echo " " 60 | } 61 | backupFile="" 62 | function backup(){ 63 | echo " " 64 | if [ -f "$destFile" ] 65 | then 66 | backupFile="$backupPath/$projectName.jar.`date +%Y%m%d%H%M%S`" 67 | cp $destFile $backupFile 68 | echo "backup [$destFile] -> [$backupFile]" 69 | fi 70 | echo " " 71 | } 72 | 73 | function deleteFiles(){ 74 | echo "Deleting $destFile" 75 | rm -rf $destFile 76 | #echo "Deleting $destConfigFolder" 77 | #rm -rf $destConfigFolder 78 | echo "Deleting $dstLogFile" 79 | rm -rf $dstLogFile 80 | echo " " 81 | } 82 | 83 | function copyFiles(){ 84 | echo "Copying files from $sourFile" 85 | cp $sourFile $destFile 86 | #echo "Copying files from $sourConfigFolder" 87 | #cp -r $sourConfigFolder $destConfigFolder 88 | echo " " 89 | } 90 | 91 | JAVA_OPTS="" 92 | JAVA_MEM_OPTS="" 93 | JAVA_DEBUG_OPTS="" 94 | JAVA_JMX_OPTS="" 95 | function run(){ 96 | JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true" 97 | JAVA_MEM_OPTS="" 98 | BITS=`java -version 2>&1 | grep -i 64-bit` 99 | if [ -n "$BITS" ]; then 100 | JAVA_MEM_OPTS=" -server -Xmx1g -Xms1g -Xmn512m -XX:PermSize=512m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 " 101 | else 102 | JAVA_MEM_OPTS=" -server -Xms1g -Xmx2g -XX:PermSize=1024m -XX:SurvivorRatio=2 -XX:+UseParallelGC " 103 | fi 104 | JAVA_DEBUG_OPTS="" 105 | if [ "$1" = "debug" ]; then 106 | JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=5566,server=y,suspend=n " 107 | fi 108 | JAVA_JMX_OPTS="" 109 | if [ "$1" = "jmx" ]; then 110 | JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false " 111 | fi 112 | #echo "java -jar $destFile $properties" | at now + 1 minutes 113 | touch $dstLogFile | chmod 777 $dstLogFile 114 | nohup nice java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -jar $destFile $properties $> $dstLogFile 2>&1 & 115 | echo "COMMAND: nohup nice java -jar $destFile $properties $> $dstLogFile 2>&1 &" 116 | echo " " 117 | } 118 | function changeFilePermission(){ 119 | echo "Changing File Permission: chmod 777 $destFile" 120 | chmod 777 $destFile 121 | echo " " 122 | } 123 | 124 | function watch(){ 125 | tail -f $dstLogFile | 126 | while IFS= read line 127 | do 128 | echo "$msgBuffer" "$line" 129 | 130 | if [[ "$line" == *"$whatToFind"* ]]; then 131 | echo $msgAppStarted 132 | pkill tail 133 | fi 134 | done 135 | } 136 | 137 | ### FUNCTIONS CALLS 138 | ##################### 139 | # Use Example of this file. Args: enviroment | port | project name | external resourcce 140 | # BUILD_ID=dontKillMe /path/to/this/file/api-deploy.sh dev 8082 spring-boot application-localhost.yml 141 | 142 | # 1 - stop server on port ... 143 | stopServer 144 | backup 145 | # 2 - delete destinations folder content 146 | deleteFiles 147 | 148 | # 3 - copy files to deploy dir 149 | copyFiles 150 | 151 | changeFilePermission 152 | # 4 - start server 153 | run 154 | 155 | # 5 - watch loading messages until ($whatToFind) message is found 156 | watch -------------------------------------------------------------------------------- /demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.example 8 | springboot-jenkins 9 | 1.0-SNAPSHOT 10 | 11 | 12 | demo 13 | jar 14 | 15 | 16 | UTF-8 17 | UTF-8 18 | 1.7 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-actuator 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-test 34 | test 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-maven-plugin 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /demo/src/main/java/com/example/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /demo/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | 2 | demo.aa=222 -------------------------------------------------------------------------------- /demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | management.security.enabled=false 2 | demo.aa=111 -------------------------------------------------------------------------------- /demo/src/test/java/com/example/demo/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /doc/image/jenkins-config1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalldok/springboot-jenkins/4ab31e6163216932f5319de148c20eb38fb4d1a7/doc/image/jenkins-config1.png -------------------------------------------------------------------------------- /doc/image/jenkins-config2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalldok/springboot-jenkins/4ab31e6163216932f5319de148c20eb38fb4d1a7/doc/image/jenkins-config2.png -------------------------------------------------------------------------------- /doc/image/jenkins-config3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalldok/springboot-jenkins/4ab31e6163216932f5319de148c20eb38fb4d1a7/doc/image/jenkins-config3.png -------------------------------------------------------------------------------- /doc/image/jenkins-config4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalldok/springboot-jenkins/4ab31e6163216932f5319de148c20eb38fb4d1a7/doc/image/jenkins-config4.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.example 8 | springboot-jenkins 9 | 1.0-SNAPSHOT 10 | 11 | demo 12 | 13 | pom 14 | 15 | 16 | UTF-8 17 | 1.7 18 | 1.5.4.RELEASE 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-parent 24 | 1.5.4.RELEASE 25 | 26 | 27 | 28 | 29 | 30 | 9527 31 | smalldok 32 | 327679964@qq.com 33 | 34 | 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-dependencies 40 | ${spring-boot.version} 41 | pom 42 | import 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /springboot-jenkins-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #local://127.0.0.1:8001/springboot-demo?profile=dev&enable_debug=false&enable_jmx=false 3 | #remote://127.0.0.1:8001/springboot-demo?profile=dev&enable_debug=false&enable_jmx=false 4 | 5 | protocol="" 6 | ip="" 7 | port="" 8 | context_path="" 9 | queryStr="" 10 | profile="dev" 11 | enable_debug="false" 12 | enable_jmx="false" 13 | function help() 14 | { 15 | cat < [$backupFile]" 160 | fi 161 | echo " " 162 | } 163 | function deleteFiles(){ 164 | echo "Deleting $destFile" 165 | rm -rf $destFile 166 | #echo "Deleting $destConfigFolder" 167 | #rm -rf $destConfigFolder 168 | echo "Deleting $dstLogFile" 169 | rm -rf $dstLogFile 170 | echo " " 171 | } 172 | 173 | function copyFiles(){ 174 | echo "Copying files from $sourFile" 175 | cp $sourFile $destFile 176 | #echo "Copying files from $sourConfigFolder" 177 | #cp -r $sourConfigFolder $destConfigFolder 178 | echo " " 179 | } 180 | 181 | JAVA_OPTS="" 182 | JAVA_MEM_OPTS="" 183 | JAVA_DEBUG_OPTS="" 184 | JAVA_JMX_OPTS="" 185 | function run(){ 186 | JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true" 187 | JAVA_MEM_OPTS="" 188 | BITS=`java -version 2>&1 | grep -i 64-bit` 189 | if [ -n "$BITS" ]; then 190 | JAVA_MEM_OPTS=" -server -Xmx1g -Xms1g -Xmn512m -XX:PermSize=512m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 " 191 | else 192 | JAVA_MEM_OPTS=" -server -Xms1g -Xmx2g -XX:PermSize=1024m -XX:SurvivorRatio=2 -XX:+UseParallelGC " 193 | fi 194 | JAVA_DEBUG_OPTS="" 195 | if [ "$enable_debug" = "true" ]; then 196 | JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=5566,server=y,suspend=n " 197 | fi 198 | JAVA_JMX_OPTS="" 199 | if [ "$enable_jmx" = "true" ]; then 200 | JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false " 201 | fi 202 | #echo "java -jar $destFile $properties" | at now + 1 minutes 203 | touch $dstLogFile | chmod 777 $dstLogFile 204 | nohup nice java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -jar $destFile $properties $> $dstLogFile 2>&1 & 205 | echo "COMMAND: nohup nice java -jar $destFile $properties $> $dstLogFile 2>&1 &" 206 | echo " " 207 | } 208 | function changeFilePermission(){ 209 | echo "Changing File Permission: chmod 777 $destFile" 210 | chmod 777 $destFile 211 | echo " " 212 | } 213 | 214 | function watch(){ 215 | tail -f $dstLogFile | 216 | while IFS= read line 217 | do 218 | echo "$msgBuffer" "$line" 219 | 220 | if [[ "$line" == *"$whatToFind"* ]]; then 221 | echo $msgAppStarted 222 | pkill tail 223 | fi 224 | done 225 | } 226 | 227 | ### FUNCTIONS CALLS 228 | ##################### 229 | # Use Example of this file. Args: enviroment | port | project name | external resourcce 230 | # BUILD_ID=dontKillMe /path/to/this/file/api-deploy.sh dev 8082 spring-boot application-localhost.yml 231 | 232 | # 1 - stop server on port ... 233 | stopServer 234 | backup 235 | # 2 - delete destinations folder content 236 | deleteFiles 237 | 238 | # 3 - copy files to deploy dir 239 | copyFiles 240 | 241 | changeFilePermission 242 | # 4 - start server 243 | run 244 | 245 | # 5 - watch loading messages until ($whatToFind) message is found 246 | watch --------------------------------------------------------------------------------