在生产环境中,往往服务器有多台,每次增量发布都需要把代码覆盖到每台服务器上面和进行备份,这样费时又费力,所有需要有一套自动化发布的流程,我这次记录的是我在工作中用到的一套发布流程和脚本,大家可以参考学习一下.
首先,用到的是apache基金会的ant项目.
所有版本下载地址:https://archive.apache.org/dist/ant/binaries/
我这边用的是1.9.2版本
一般在生产环境中,应用目录如下:
如果没有release目录,自己新建一个.
然后将下载好的apache-ant-1.9.2放到release目录下
并在release目录下新建一个目录,取名一般为需要发布的应用服务名,用于区分,因为一台服务器可能有多个应用服务需要发布,A应用和B应用,所以需要用应用服务名来区分发布的应用
A或者B发布目录存放如下文件:
首先,done目录是存放每次需要发布的代码,格式是tgz包,代码目录需要到根目录下,一般是web目录,比如web-WEB-INF-classes-.....等等,将需要发布的包放入done下面,用打包命令进行打包 tar -zcvf A.tgz web
ant-multi-shelll.xml 文件如下 可以直接copy,不需要改动
<?xml version="1.0" encoding="UTF-8"?>
<project name="ant-multi-shell" xmlns:ac="antlib:net.sf.antcontrib">
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask" />
<macrodef name="host-property">
<attribute name="filename" default="apphosts.xml" />
<attribute name="hostip" default="" />
<sequential>
<property name="hosts" value="" />
<property name="rhosts" value="" />
<property name="host" value="" />
<hostinfo prefix="localhost"/>
<xmltask source="@{filename}">
<call path="/application">
<param name="release.path" path="release/text()"/>
<actions>
<property name="release.path" value="@{release.path}" />
</actions>
</call>
<call path="/application/host">
<param name="host.username" path="username/text()"/>
<param name="host.password" path="password/text()"/>
<param name="host.ip" path="ip/text()"/>
<actions>
<propertyregex override="yes" property="hosts" input="@{host.username}:@{host.password}@@" regexp="(.*)" select="${hosts}\1"/>
<propertyregex override="yes" property="hosts" input="@{host.ip};" regexp="(.*)" select="${hosts}\1"/>
<ac:if>
<ac:equals arg1="${localhost.ADDR4}" arg2="@{host.ip}" />
<ac:then/>
<ac:else>
<propertyregex override="yes" property="rhosts" input="@{host.username}:@{host.password}@@" regexp="(.*)" select="${rhosts}\1"/>
<propertyregex override="yes" property="rhosts" input="@{host.ip};" regexp="(.*)" select="${rhosts}\1"/>
</ac:else>
</ac:if>
<ac:if>
<ac:equals arg1="@{hostip}" arg2="@{host.ip}" />
<ac:then>
<propertyregex override="yes" property="host" input="@{host.username}:@{host.password}@@" regexp="(.*)" select="${host}\1"/>
<propertyregex override="yes" property="host" input="@{host.ip};" regexp="(.*)" select="${host}\1"/>
</ac:then>
</ac:if>
</actions>
</call>
</xmltask>
</sequential>
</macrodef>
<macrodef name="multi-scp">
<attribute name="hosts" />
<attribute name="destpath" default="" />
<attribute name="filename" />
<sequential>
<ac:for list="@{hosts}" param="host" delimiter=";" parallel="true">
<ac:sequential>
<scp trust="yes" todir="@{host}:@{destpath}/done" file="@{filename}" />
</ac:sequential>
</ac:for>
</sequential>
</macrodef>
<macrodef name="multi-ssh">
<attribute name="hosts" />
<attribute name="cmmdpath" default="" />
<attribute name="commands" />
<attribute name="parallel" default="true"/>
<attribute name="keybased" default="no"/>
<sequential>
<ac:for list="@{hosts}" param="host" delimiter=";" parallel="@{parallel}">
<ac:sequential>
<local name="host.username"/>
<local name="host.password"/>
<local name="host.ip"/>
<propertyregex property="host.username" input="@{host}" regexp="(.*):" select="\1"/>
<propertyregex property="host.password" input="@{host}" regexp=":(.*)@" select="\1"/>
<propertyregex property="host.ip" input="@{host}" regexp="@(.*)" select="\1"/>
<ac:if>
<ac:equals arg1="@{keybased}" arg2="yes" />
<ac:then>
<sshexec trust="yes" host="${host.ip}" username="${host.username}" keyfile="${user.home}/.ssh/id_dsa" command="cd @{cmmdpath}; @{commands};"/>
</ac:then>
<ac:else>
<sshexec trust="yes" host="${host.ip}" username="${host.username}" password="${host.password}"
command="cd @{cmmdpath}; @{commands};"/>
</ac:else>
</ac:if>
</ac:sequential>
</ac:for>
</sequential>
</macrodef>
</project>
apphosts.xml 文件是配置服务器信息的
<?xml version="1.0" encoding="UTF-8"?>
<application>
<name>请填写服务名 A</name>
<release>请填写发布目录 /tpdata/release/A</release>
<host>
<ip>服务器一IP</ip>
<username>你懂</username>
<password>你懂</password>
</host>
<host>
<ip>服务器二IP</ip>
<username>你懂</username>
<password>你懂</password>
</host>
多个就填写多个
</application>
batch-deploy.sh -->
#!/bin/bash
app_path=/tpdata/applications/A 填写应用目录
app_path=${app_path%/}
app_root=${app_path%/*}
app_name=${app_path##*/}
file_prex=${1%.*}
echo "the application‘s location is $app_path"
echo "the release‘s signature is $file_prex"
file_tgz=$file_prex.tgz
if test -f $file_tgz; then
echo "deploying $file_tgz ..."
else
echo "can not find file $file_tgz"
exit
fi
ant -buildfile build_msh.xml upload-file -Dfilename="$file_tgz"
ant -buildfile build_msh.xml multi-shell -Dcommands="sh ./deploy.sh $file_tgz" -Dparallel=true
batch-restart-one.sh
#!/bin/bash
domain_path=/tpsys/applications/testdomain/script [停启服务器脚本目录]
ant -buildfile build_msh.xml remote-shell -Dremoteip="服务器1IP" -Dcommands="cd $domain_path;sh 停脚本"&
ant -buildfile build_msh.xml remote-shell -Dremoteip="服务器2IP" -Dcommands="cd $domain_path;sh 停脚本"&
ant -buildfile build_msh.xml remote-shell -Dremoteip="服务器1IP" -Dcommands="cd $domain_path;sh 启脚本"&
ant -buildfile build_msh.xml remote-shell -Dremoteip="服务器2IP" -Dcommands="cd $domain_path;sh 启脚本"&
date
build_msh.xml 直接copy 不需要改
<?xml version="1.0" encoding="UTF-8"?>
<project name="msh-build" default="multi-shell" basedir=".">
<import file="ant-multi-shelll.xml"/>
<target name="init">
<host-property filename="apphosts.xml" />
</target>
<target name="upload-file" depends="init">
<property name="filename" value="test.sh"/>
<property name="destpath" value="${release.path}" />
<multi-scp hosts="${rhosts}" destpath="${destpath}" filename="${filename}" />
</target>
<target name="multi-upload" depends="init">
<property name="filename" value="test.sh"/>
<property name="destpath" value="${release.path}" />
<multi-scp hosts="${hosts}" destpath="${destpath}" filename="${filename}" />
</target>
<target name="remote-upload">
<property name="filename" value="test.sh"/>
<property name="remoteip" value="192.168.59.137" />
<property name="destpath" value="${release.path}" />
<host-property filename="apphosts.xml" hostip="${remoteip}" />
<multi-scp hosts="${host}" destpath="${destpath}" filename="${filename}" />
</target>
<target name="multi-shell" depends="init">
<property name="cmmdpath" value="${release.path}" />
<property name="commands" value="cat 1.txt" />
<property name="parallel" value="false" />
<multi-ssh hosts="${hosts}" cmmdpath="${cmmdpath}" commands="${commands}" parallel="${parallel}" />
</target>
<target name="remote-shell">
<property name="remoteip" value="192.168.59.137" />
<property name="cmmdpath" value="${release.path}" />
<property name="commands" value="cat 1.txt" />
<host-property filename="apphosts.xml" hostip="${remoteip}" />
<multi-ssh hosts="${host}" cmmdpath="${cmmdpath}" commands="${commands}" parallel="false" />
</target>
</project>
deploy.sh
#!/bin/bash
app_path=/tpdata/applications/A
app_path=${app_path%/}
app_root=${app_path%/*}
app_name=${app_path##*/}
file_prex=${1%.*}
today=`date +%Y-%m-%d`
echo "the application‘s app_path is $app_path"
echo "the application‘s app_root is $app_root"
echo "the application‘s app_name is $app_name"
echo "the release‘s signature is $file_prex"
file_tgz=$file_prex.tgz
if test -f $file_tgz; then
echo "deploying $file_tgz ..."
else
echo "can not find file $file_tgz"
exit
fi
mkdir -p done
if test -f done/$file_prex.$today.tgz; then
echo "find done/$file_prex.$today.tgz, skip full backup."
else
ls -x1 $app_path > $app_name.list
tar -czf $app_name.$today.tgz -C $app_path -T $app_name.list
mv $app_name.$today.tgz done/
rm $app_name.list
fi
echo "files backuping ..."
tar -tzf $file_tgz > $file_prex.list
tar -czf $file_prex.old.tgz -C $app_path -T $file_prex.list
rm $file_prex.list
mv $file_prex.old.tgz done/
echo "files updating ..."
tar -xzf $file_tgz -C $app_path
mv $file_tgz done/
echo "$file_tgz" >> done/$app_name.$today.released
echo "`date ‘+%Y-%m-%d %H:%M:%S‘`: [$1] deploy done. " >> $app_name.release.log
echo "deply done."
recover.sh
#!/bin/bash
app_path=/tpdata/applications/A
app_path=${app_path%/}
app_root=${app_path%/*}
app_name=${app_path##*/}
file_prex=${1%.*}
file_prex=${file_prex##*/}
today=`date +%Y-%m-%d`
echo "the application‘s location is $app_path"
echo "the release signature is $file_prex"
file_tgz=$file_prex.old.tgz
if test -f "done/$file_tgz"; then
echo "recovering $file_tgz ..."
else
echo "can not find file $file_tgz"
exit
fi
file_release=$app_name.$today.released
if test $2; then
file_release=$app_name.$2.released
fi
if !(test -f "done/$file_release"); then
echo "can not find file $file_release"
exit
fi
echo "files backuping ..."
tar -tzf done/$file_tgz > $file_prex.list
tar -czf $file_prex.cover.tgz -C $app_path -T $file_prex.list
mv $file_prex.cover.tgz done/
rm $file_prex.list
rm -rf $app_path/web
echo "files updating ..."
tar -xzf "done/$file_tgz" -C $app_path
sed -i ‘/‘"$file_prex.tgz"‘/d‘ done/$file_release
echo "`date ‘+%Y-%m-%d %H:%M:%S‘`: [$file_prex.tgz] recover done. " >> $app_name.release.log
echo "recover done."
如上,就把自动化发布的脚本都准备全了,下面需要配置一下环境变量
到/home/weblogic/目录下 我的.bash_profile文件在这个目录
命令如下
cd /home/weblogic
vim .bash_profile
新增:
ANT_HOME=/tpsys/applictions/release/apache-ant-1.9.2 [配置ANT目录]
JAVA_HOME=/usr/java/jdk1.6.0_29 [JDK目录]
PATH=$ANT_HOME/bin:$JAVA_HOME/bin:$PATH:$HOME/.local/bin:$HOME/bin
保存后执行source .bash_profile使生效
这些配置如果有多台服务器,则每台都需要配置
然后每次发布只需要将需要发布的包打成tgz包放入其中一台服务器的done目录下,
在执行 sh batch-deploy.sh done/A.tgz 就会自动将发布包分发到所有服务器进行覆盖,并且备份原代码.
最后执行重启脚本 sh batch-restart-one.sh
当发布出现问题,需要回退时候 执行 sh recover.sh
如果出现文件权限文件,请执行 chmod 777 文件名
大功告成!
原文:https://www.cnblogs.com/wnhbx/p/11652245.html