jenkins搭建、自动化构建
资料参考
- 官网地址:https://www.jenkins.io/
- 下载地址:https://www.jenkins.io/download/
- 文档地址:
- 《Jenkins持续集成入门到精通》
- 自动化部署Jenkins从环境配置到项目开发【黑马程序员Java教程】
- 使用 Jenkins 部署 Spring Boot
- jenkins简介及docker部署
一、项目源码加密方案–xjar
xjar官网地址: https://github.com/core-lib/xjar
1.改造项目(spring-boot + maven环境)
该项为开发人员改造项目用,运维人员可以跳过,直接看项目编译和项目部署 ● 在pom.xml中 ,添加xjar相关的编译(需要在 spring-boot-maven-plugin 插件之后)
<!-- 添加 XJar Maven 插件 -->
<plugin>
<groupId>com.github.core-lib</groupId>
<artifactId>xjar-maven-plugin</artifactId>
<version>4.0.2</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
<phase>package</phase>
<!-- 或使用
<phase>install</phase>
-->
<configuration>
<!-- optional
<password>io.xjar</password>
<algorithm/>
<keySize/>
<ivSize/>
<includes>
<include/>
</includes>
-->
<!-- 相对于classpath,需要排除加密文件的ant表达式 -->
<excludes>
<exclude>/**/*.sql</exclude>
<exclude>/**/*.xml</exclude>
<exclude>/**/*.jpg</exclude>
<exclude>/**/*.xlsx</exclude>
<exclude>/**/*.yml</exclude>
<exclude>/**/*.yaml</exclude>
<exclude>/**/*.properties</exclude>
<exclude>/**/*.html</exclude>
<exclude>/**/*.js</exclude>
<exclude>/**/*.css</exclude>
</excludes>
<!--
<sourceDir/>
<sourceJar/>
<targetDir/>
<targetJar/>
-->
</configuration>
</execution>
</executions>
</plugin>
● 指定xjar插件的下载地址
<!-- 设置 jitpack.io 插件仓库 -->
<pluginRepositories>
<pluginRepository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</pluginRepository>
</pluginRepositories>
2.项目编译
原本的编译命令为 mvn clean install -Dmaven.test.skip=true,现需要在原有的命令后面加上加密密码, 密码为 123321 mvn clean install -Dmaven.test.skip=true -Dxjar.password=123321
原本项目生成*.jar ,那么现在编译后生成的目录会比原本多出 *.xjar , xjar.go, xjar_agentable.go 这三个文件
3.项目部署
因为xjar 支持windows平台和linux平台,所以需要实现用xjar.go 来生成 xjar文件的启动器,启动器与xjar文件具有一一对应的关系,防止文件包被篡改,即,每次mvn打包生成的xjar.go和xjar包一一对应,即便密码相同也不能通用
- 部署机: 用来运行的项目的机器
- 编译机: 需要和部署机属于相同的系统环境,用于生成项目启动器,必要时可以用部署机替代
编译机环境要求:
- java环境
- go语言环境
编译过程(以linux环境为例)
- 将 *.xjar和 xjar.go 两个文件拷贝进部署机上
- 在xjar.go 文件的目录下,运行 go build xjar.go ,执行结束可以看到当前目录下产生 xjar 的可执行文件
- 在当前目录,直接运行命令即可执行成功
# java 如果环境变量没有配置好,需要指定java的绝对路径
# 如果配置文件需要指定环境,例如: 配置文件为application-dev.properties,则需要在最后加上
--spring.profiles.active=dev nohup ./xjar java -jar demo-1.0.2.xjar &>/dev/null
二、Jenkins搭建
Jenkins持续集成入门到精通-2、Jenkins安装和持续集成环境配置
三、Jenkins配置开发环境后端包自动构建
前置:首页/系统管理 -> 系统配置 -> Publish over SSH -> SSH Servers -> 添加ssh server节点信息
1.新建项目视图分组,如“测试系统”
2.选择分组,新建构建任务,输入任务名称,如:XX_SERVER_Deploy, 选择“构建一个maven项目”,点击ok
3.选择 XX_SERVER_Deploy 任务,点击“配置”
3.1 General
负责人:
功能:后端打包上传开发环境
路径:server_ip1/data/packages server_ip2/data/packages
3.2 Maven Info Plugin Configuration
勾选参数化构建过程
3.3 点击添加参数:选择Git参数
3.4 点击添加参数:Extended Choice Paramter
点击添加参数:Extended Choice Paramter 配置另一个节点服务名和服务包
3.5 点击添加参数:字符参数,配置变量,起服务时如需指定配置,可通过这里配置指定
3.6 点击添加参数:选项参数,打包-配置 环境选择
4.源码管理
5.构建触发器
6.post steps
## 执行shell
project_name=$JOB_NAME
jarNamelist="$jarNamelist11,$jarNamelist10" //3.4配置的节点名称
/data/jenkins/shSample/deploy_SERVER_new.sh $project_name $jarNamelist $extraCommand
附shell脚本1:deploy_SERVER_new.sh
#!/bin/bash
#function:配置bulidtmp的svn信息,将打包好的jar包上传到指定SVN
#parameter:
#参数1:项目名称
#参数2:所需打包的jar包名列表
set -x
#init
Project_Name=$1
namelist=$2
extraCommand=$3
#Project_Path=/data/jenkins/workspace/$Project_Name
Project_Path=`pwd`
Build_Time=`date "+%Y%m%d"`
Buildtmp_Path=/data/jenkins/buildtmp/$Project_Name
#init log
function log_msg ()
{
echo "${0#./} : $@"
}
#获取git commitid和readme中的版本号,注意版本号必须为三位
cd $Project_Path
Git_Version=`git rev-list HEAD | sed -n 1p | cut -c1-7`
if [ ! -n "$Git_Version" ]
then
log_msg "Git_Version is empty"
exit 1
fi
Project_Version=`ls | awk '/README.md|readme.md/'|xargs cat | grep curVersion | sed 's/.*\=\([[:alpha:]]\|\s\)*\([[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\)\(\w\|\s\)*/\2/g'`
if [ ! -n "$namelist" ]
then
re_Name=$Project_Name
if [ ! -d $Buildtmp_Path/$re_Name ] ;then
mkdir -p $Buildtmp_Path/$re_Name
fi
Package_re="$re_Name".zip
JarName_re="$re_Name"-"$Project_Version".jar
cd "$Buildtmp_Path"/$re_Name
rm -rf ./*
cp -f "$Project_Path"/target/*.jar ./$JarName_re
#mv $re_Name-1.0-SNAPSHOT.jar $JarName_re
md5sum $JarName_re > "$JarName_re".md5
cp -rf "$Project_Path"/target/config .
#cp /data/jenkins/scripts/deploy.sh .
cp /data/jenkins/shSample/deployChangeCommand.sh ./deploy.sh
sed -i "s/extraCommand=/extraCommand=$extraCommand/g" deploy.sh
zip -r $Package_re ./ -x .svn\*
mv -f $Package_re $Project_Path
else
#循环
for name in ${namelist//,/ };
do
re_Name=$name
if [ ! -d $Buildtmp_Path/$re_Name ] ;then
mkdir -p $Buildtmp_Path/$re_Name
fi
Package_re="$re_Name".zip
JarName_re="$re_Name"-"$Project_Version".jar
cd "$Buildtmp_Path"/$re_Name
rm -rf ./*
cp -f "$Project_Path"/$re_Name/target/*.jar ./$JarName_re
#mv $re_Name-1.0-SNAPSHOT.jar $JarName_re
md5sum $JarName_re > "$JarName_re".md5
cp -rf "$Project_Path"/$re_Name/target/config .
#cp /data/jenkins/scripts/deploy.sh .
cp /data/jenkins/shSample/deployChangeCommand.sh ./deploy.sh
sed -i "s/extraCommand=/extraCommand=$extraCommand/g" deploy.sh
zip -r $Package_re ./ -x .svn\*
mv -f $Package_re $Project_Path
done
fi
附shell脚本2::deployChangeCommand.sh
#!/bin/sh
#VERSION = 1.1
#警告!!!:该脚本stop部分使用系统kill命令来强制终止指定的java程序进程。
#在杀死进程前,未作任何条件检查。在某些情况下,如程序正在进行文件或数据库写操作,
#可能会造成数据丢失或数据不完整。如果必须要考虑到这类情况,则需要改写此脚本,
#JAVA_HOME=
#执行程序启动所使用的系统用户,考虑到安全,不推荐使用root帐号
#RUNNING_USER=web02
#Java程序所在的目录(classes的上一级目录)
#APP_HOME=$2
#需要启动的Java主程序(main方法类)
APP_MAINCLASS=$2
#实例生效配置
Profile=$3
#启动命令额外参数
Command=$4
# #kafka启动服务实例个数
# InstanceCount=$4
# #kafka启动服务实例编号
# InstanceNo=$5
#java虚拟机启动参数
#JAVA_OPTS="-ms512m -mx512m -Xmn256m -Djava.awt.headless=true -XX:MaxPermSize=128m -Xdebug -Xrunjdwp:transport=dt_socket,address=17003,server=y,suspend=n"
JAVA_OPTS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/java_heapdump.hprof"
extraCommand=
psid=0
checkpid() {
# javaps=`$JAVA_HOME/bin/jps -l | grep $APP_MAINCLASS`
javaps=`jps -l | grep $APP_MAINCLASS`
if [ -n "$javaps" ]; then
psid=`echo $javaps | awk '{print $1}'`
else
psid=0
fi
}
###################################
#(函数)启动程序
#说明:
#1. 首先调用checkpid函数,刷新$psid全局变量
#2. 如果程序已经启动($psid不等于0),则提示程序已启动
#3. 如果程序没有被启动,则执行启动命令行
#4. 启动命令执行后,再次调用checkpid函数
#5. 如果步骤4的结果能够确认程序的pid,则打印[OK],否则打印[Failed]
#注意:echo -n 表示打印字符后,不换行
###################################
start() {
checkpid
if [ $psid -ne 0 ]; then
echo "================================"
echo "warn: $APP_MAINCLASS already started! (pid=$psid)"
echo "================================"
else
#必须声明profiles
if [ ! -n "$Profile" ];
then
#没有输入环境变量
echo "ERROR: profile can't be null"
echo "Usage: $0 {start|stop} appname {test|prod|dev} (instance-count instance-no)"
else
echo -n "Starting $APP_MAINCLASS ..."
#可选参数
if [ ! -n "$Command" ] ;
then
#nohup java $JAVA_OPTS -jar $APP_MAINCLASS --spring.profiles.active=$Profile $extraCommand > /dev/null 2>&1 &
nohup java $JAVA_OPTS $extraCommand -jar $APP_MAINCLASS --spring.profiles.active=$Profile > /dev/null 2>&1 &
else
#nohup java $JAVA_OPTS -jar $APP_MAINCLASS --spring.profiles.active=$Profile $extraCommand $Command > /dev/null 2>&1 &
nohup java $JAVA_OPTS $extraCommand -jar $APP_MAINCLASS --spring.profiles.active=$Profile $Command > /dev/null 2>&1 &
fi
sleep 10
checkpid
if [ $psid -ne 0 ]; then
echo "(pid=$psid) [OK]"
else
echo "[Failed]"
exit 1
fi
fi
fi
}
###################################
#说明:
#1. 首先调用checkpid函数,刷新$psid全局变量
#2. 如果程序已经启动($psid不等于0),则开始执行停止,否则,提示程序未运行
#3. 使用kill -9 pid命令进行强制杀死进程
#4. 执行kill命令行紧接其后,马上查看上一句命令的返回值: $?
#5. 如果步骤4的结果$?等于0,则打印[OK],否则打印[Failed]
#6. 为了防止java程序被启动多次,这里增加反复检查进程,反复杀死的处理(递归调用stop)。
#注意: 在shell编程中,"$?" 表示上一句命令或者一个函数的返回值
###################################
stop() {
checkpid
if [ $psid -ne 0 ]; then
echo -n "Stopping $APP_MAINCLASS ...(pid=$psid) "
kill -9 $psid
if [ $? -eq 0 ]; then
echo "[OK]"
else
echo "[Failed]"
fi
checkpid
if [ $psid -ne 0 ]; then
stop
fi
else
echo "================================"
echo "warn: $APP_MAINCLASS is not running"
echo "================================"
fi
}
###################################
#说明:
#1. 首先调用checkpid函数,刷新$psid全局变量
#2. 如果程序已经启动($psid不等于0),则提示正在运行并表示出pid
#3. 否则,提示程序未运行
###################################
status() {
checkpid
if [ $psid -ne 0 ]; then
echo "$APP_MAINCLASS is running! (pid=$psid)"
else
echo "$APP_MAINCLASS is not running"
fi
}
###################################
#(函数)打印系统环境参数
###################################
info() {
echo "System Information:"
echo "****************************"
echo `head -n 1 /etc/issue`
echo `uname -a`
echo
echo "JAVA_HOME=$JAVA_HOME"
echo `$JAVA_HOME/bin/java -version`
echo
echo "APP_HOME=$APP_HOME"
echo "APP_MAINCLASS=$APP_MAINCLASS"
echo "****************************"
}
###################################
#读取脚本的第一个参数($1),进行判断
#参数取值范围:{start|stop|restart|status|info}
#如参数不在指定范围之内,则打印帮助信息
###################################
case "$1" in
'start')
start
;;
'stop')
stop
;;
'status')
status
;;
'info')
info
;;
*)
echo "Usage: $0 {start|stop} appname {test|prod|dev} (instance-count instance-no)"
exit 1
esac
exit 0
7.构建后操作:解压包,启停节点服务
add server
Exec command
#!/bin/bash
#功能:配置server包软链接并执行
#sh /data/jenskins_server_deploy.sh $dirname $jarname $environment
#init log
source /etc/profile
function log_msg ()
{
echo "${0#./} : $@"
}
#变量1业务包所在目录
dirname="/data/packages"
#变量2jar包名
jarnamelist=$jarNamelist10
#变量3apollo的环境
environment=$environment
if [ ! -n "$jarnamelist" ]
then
jarname=$Project_Name
cd $dirname
unzip -o "$jarname.zip" -d $jarname
#设置软链接
ln -snf $dirname/$jarname /data/$jarname
#停服务
cd /data/$jarname
sh deploy.sh stop *.jar
sleep 2s
#启服务
sh deploy.sh start *.jar $environment
sleep 10s
#查看微服务端口是否开启
netstat -untlp | grep `jps -l | grep -v grep |grep $jarname|awk '{print $1}'`
rm -rf "$jarname.zip"
else
#循环
for name in ${jarnamelist//,/ };
do
jarname=$name
cd $dirname
unzip -o "$jarname.zip" -d $jarname
#设置软链接
ln -snf $dirname/$jarname /data/$jarname
#停服务
cd /data/$jarname
sh deploy.sh stop *.jar
sleep 2s
#启服务
sh deploy.sh start *.jar $environment
sleep 10s
#查看微服务端口是否开启
netstat -untlp | grep `jps -l | grep -v grep |grep $jarname|awk '{print $1}'`
rm -rf "$jarname.zip"
done
fi
点击add server:配置另一个节点服务和启动脚本 Exec command
附shell脚本3:jenskins_server_deploy.sh
#!/bin/bash
#功能:配置server包软链接并执行
#sh /data/jenskins_server_deploy.sh $dirname $jarname $environment
#init log
function log_msg ()
{
echo "${0#./} : $@"
}
#变量1含版本号的目录名
dirname=$1
#变量2jar包名
jarname=$2
#变量3apollo的环境
environment=$3
#设置软链接
ln -snf /data/packages/$dirname /data/$jarname
#停服务
cd /data/$jarname
sh deploy.sh stop *.jar
sleep 2s
#启服务
sh deploy.sh start *.jar $environment
sleep 10s
#查看微服务端口是否开启
netstat -untlp | grep `jps -l | grep -v grep |grep $jarname|awk '{print $1}'`
8.配置完成,执行构建
四、提测构建后端打包到svn
1.post steps之前的步骤参考“三、Jenkins配置开发环境后端包自动构建” 步骤1-6
2.post steps/执行shell
project_name=$JOB_NAME
## svn提测包路径自行配置修改
svnUrl=svn://ip:port/Version/xxx_SERVER/
cd /data/jenkins/shSample
#./pack_SERVER.sh $project_name $Environment $svnUrl $jarNamelist
if [ ! -n "$extraCommand" ] ;
then
./pack_SERVER.sh $project_name TEST $svnUrl $jarNamelist
else
./pack_SERVER_ExtraCommand.sh $project_name TEST $svnUrl $jarNamelist $extraCommand
fi
附shell脚本4:pack_SERVER.sh
#!/bin/bash
#function:配置bulidtmp的svn信息,将打包好的jar包上传到指定SVN
#parameter:
#参数1:项目名称
#参数2:编译环境
#参数3:svn地址 最后无需斜杠
#参数4:所需打包的jar包名列表
set -x
#init
#Project_Name=HORN_SERVER
namelist=$4
svnUrl=$3
Environment=$2
Project_Name=$1
Project_Path=/data/jenkins/workspace/$Project_Name
Build_Time=`date "+%Y%m%d"`
#init log
function log_msg ()
{
echo "${0#./} : $@"
}
#Git info
cd $Project_Path
Git_Version=`git rev-list HEAD | sed -n 1p | cut -c1-7`
if [ ! -n "$Git_Version" ]
then
log_msg "Git_Version is empty"
exit 1
fi
#Project_Version=`cat README.md | sed -n 1p | cut -c 12-`
Project_Version=`ls | awk '/README.md|readme.md/'|xargs cat | grep curVersion | sed 's/.*\=\([[:alpha:]]\|\s\)*\([[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\)\(\w\|\s\)*/\2/g'`
#tar
#for name in $namelist
for name in ${namelist//,/ };
do
re_Name=$name
Buildtmp_Path=/data/jenkins/buildtmp/$Project_Name/$Environment/$re_Name
svnURL=$svnUrl/$Environment/$re_Name
#创建buildtmp目录并自动初始化SVN:创建svn目录并svn co
if [ ! -d $Buildtmp_Path ] ;then
mkdir -p $Buildtmp_Path
svn mkdir --parents -m "create $Project_Name directory" $svnURL
cd $Buildtmp_Path
svn co $svnURL .
fi
Package_re="$re_Name"_"$Project_Version"."$Git_Version"_Build"$Build_Time".zip
JarName_re="$re_Name"-"$Project_Version".jar
# if [ ! -d "$Buildtmp_Path"/$re_Name ] ;then
# mkdir -p "$Buildtmp_Path"/$re_Name
# fi
cd "$Buildtmp_Path"
rm -rf ./*
cp -f "$Project_Path"/$re_Name/target/*.jar ./$JarName_re
#cp -f "$Project_Path"/$re_Name/target/$re_Name-1.0-SNAPSHOT.jar ./$JarName_re
#mv $re_Name-1.0-SNAPSHOT.jar $JarName_re
md5sum $JarName_re > "$JarName_re".md5
cp -rf "$Project_Path"/$re_Name/target/config .
cp /data/jenkins/scripts/deploy.sh .
zip -r $Package_re ./ -x .svn\*
svn add "$Package_re"
svn commit -m "add $Package_re"
echo "包SVN地址"
echo $svnURL/$Package_re
done
附shell脚本5:pack_SERVER_ExtraCommand.sh
#!/bin/bash
#function:配置bulidtmp的svn信息,将打包好的jar包上传到指定SVN
#parameter:
#参数1:项目名称
#参数2:编译环境
#参数3:svn地址 最后无需斜杠
#参数4:所需打包的jar包名列表
set -x
#init
#Project_Name=HORN_SERVER
extraCommand=$5
namelist=$4
svnUrl=$3
Environment=$2
Project_Name=$1
Project_Path=/data/jenkins/workspace/$Project_Name
Build_Time=`date "+%Y%m%d"`
#init log
function log_msg ()
{
echo "${0#./} : $@"
}
#Git info
cd $Project_Path
Git_Version=`git rev-list HEAD | sed -n 1p | cut -c1-7`
if [ ! -n "$Git_Version" ]
then
log_msg "Git_Version is empty"
exit 1
fi
#Project_Version=`cat README.md | sed -n 1p | cut -c 12-`
Project_Version=`ls | awk '/README.md|readme.md/'|xargs cat | grep curVersion | sed 's/.*\=\([[:alpha:]]\|\s\)*\([[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\)\(\w\|\s\)*/\2/g'`
#tar
#for name in $namelist
for name in ${namelist//,/ };
do
re_Name=$name
Buildtmp_Path=/data/jenkins/buildtmp/$Project_Name/$Environment/$re_Name
svnURL=$svnUrl/$Environment/$re_Name
#创建buildtmp目录并自动初始化SVN:创建svn目录并svn co
if [ ! -d $Buildtmp_Path ] ;then
mkdir -p $Buildtmp_Path
svn mkdir --parents -m "create $Project_Name directory" $svnURL
cd $Buildtmp_Path
svn co $svnURL .
fi
Package_re="$re_Name"_"$Project_Version"."$Git_Version"_Build"$Build_Time".zip
JarName_re="$re_Name"-"$Project_Version".jar
# if [ ! -d "$Buildtmp_Path"/$re_Name ] ;then
# mkdir -p "$Buildtmp_Path"/$re_Name
# fi
cd "$Buildtmp_Path"
rm -rf ./*
cp -f "$Project_Path"/$re_Name/target/*.jar ./$JarName_re
#cp -f "$Project_Path"/$re_Name/target/$re_Name-1.0-SNAPSHOT.jar ./$JarName_re
#mv $re_Name-1.0-SNAPSHOT.jar $JarName_re
md5sum $JarName_re > "$JarName_re".md5
cp -rf "$Project_Path"/$re_Name/target/config .
#cp /data/jenkins/scripts/deploy.sh .
cp /data/jenkins/shSample/deployChangeCommand.sh ./deploy.sh
sed -i "s/extraCommand=/extraCommand=$extraCommand/g" deploy.sh
zip -r $Package_re ./ -x .svn\*
svn add "$Package_re"
svn commit -m "add $Package_re"
echo "包SVN地址"
echo $svnURL/$Package_re
done
五、提测构建前端打包到svn
1.新建任务时选择
2.基础配置
3.构建:执行shell
#project_name指定的项目名称需要小写,svnUrl最后无斜杠
project_name=$JOB_NAME
svnUrl=svn://ip:port/Version/xxx_WEB
#cnpm install
cnpm install --registry=https://registry.npm.taobao.org
npm run build
cd /data/jenkins/shSample
./pack_WEB.sh $project_name $Environment $svnUrl
附shell脚本6:pack_WEB.sh
#!/bin/bash
#function:配置bulidtmp的svn信息,将打包好的web包上传到指定SVN
#parameter:
#参数1:项目名称
#参数2:编译环境
#参数3:svn地址 最后无需斜杠
#!/bin/bash
set -x
#init
Project_Name=$1
Project_Path=/data/jenkins/workspace/$Project_Name
Environment=$2
Build_Time=`date "+%Y%m%d"`
Buildtmp_Path=/data/jenkins/buildtmp/$Project_Name/$Environment
svnUrl=$3
svnURL=$svnUrl/$Environment
#init log
function log_msg ()
{
echo "${0#./} : $@"
}
#Git info
cd $Project_Path
Git_Version=`git rev-list HEAD | sed -n 1p | cut -c1-7`
if [ ! -n "$Git_Version" ]
then
log_msg "Git_Version is empty"
exit 1
fi
Project_Version=`ls | awk '/README.md|readme.md/'|xargs cat | grep curVersion | sed 's/.*\=\([[:alpha:]]\|\s\)*\([[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\)\(\w\|\s\)*/\2/g'`
Package_Name="$Project_Name"_"$Project_Version"."$Git_Version"_Build"$Build_Time".zip
#build
#cnpm install
#npm run build
#创建buildtmp目录并自动初始化SVN:创建svn目录并svn co
if [ ! -d $Buildtmp_Path ] ;then
mkdir -p $Buildtmp_Path
svn mkdir --parents -m "create $Project_Name directory" $svnURL
cd $Buildtmp_Path
svn co $svnURL .
fi
#tar
cd $Project_Path
zip -r $Package_Name dist
if [ $? -ne 0 ]
then
log_msg "Tar $Package_Name Failed"
exit 1
fi
#publish
cd $Buildtmp_Path
rm -rf *.zip
mv -f $Project_Path/"$Package_Name" $Buildtmp_Path
svn add "$Package_Name"
svn commit -m "add $Package_Name"
echo "包SVN地址"
echo "$svnURL/$Package_Name"
set +x