java项目自动部署方案(1):wagon-maven-plugin

该方法适用于maven构建的项目,自动部署需要用到maven插件wagon-maven-plugin

当配置插件后,部署流程如下:

  1. 客户端通过maven打包项目(package)
  2. 插件会自动将包上传到配置的服务器
  3. 插件调用wagon-ssh库执行部署脚本

上述流程中每次都需要手动操作的就只有第1条,其他都可以自动完成,这种方案很适用于开发过程中的测试部署,具体配置方法如下(想直接查看所有配置的代码见文末配置代码)。

配置wagon-maven-plugin

配置wagon-maven-plugin分为4个部分:

  1. 配置服务器认证
  2. 配置插件执行阶段(阶段简单说就是插件的执行时机,比如package之后,可以搜索maven生命周期关键词了解)。
  3. 配置上传包的目标(目标简单说就是要插件做的事情,一个插件可以做很多事情,一件事情就是一个目标)
  4. 配置执行部署脚本目标

1. 配置服务器认证

在maven的配置文件settings.xml(一般在用户目录下的.m2文件夹下)中配置服务器认证信息,即用户和密码,找到文件的大概121行可以看到配置server信息的注释,在注释后面添加如下代码。

1
2
3
4
5
<server>
<id>127.0.0.1</id>
<username>root</username>
<password>root</password>
</server>

其中,

  • 标签<id>是该配置的唯一编号,后面配置插件连接服务器会用到,建议配置为服务器ip
  • 标签<username>是服务器登录用户名
  • 标签<password>是服务器登录密码

2. 配置插件执行阶段

执行打包命令完成打包后,就要执行插件了,那么插件的执行时机就是package。pom.xml中新增如下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>2.0.0</version>
<!-- 定义执行 -->
<executions>
<execution>
<id>upload-and-deploy</id>
<!-- 插件在maven的package阶段执行,即打包后执行 -->
<phase>package</phase>
</execution>
</executions>
</plugin>

其中,

  • 标签<execution>表示定义执行,具体为后面要配置的上传包和执行部署脚本。
  • 标签<id>表示这个执行的id,取一个有意义的名称即可。
  • 标签<phase>表示这个插件在package阶段执行,即打包完成后执行。

简单描述下阶段以及如何配置插件在阶段中执行。比如命令mvn clean package,这个命令中有2个阶段,即cleanpackage,如果想要pluginA插件在package之后执行,就可以执行命令mvn clean package pluginA。如果希望命令简单一些,可以将插件的phase标签配置为package,这时候执行命令mvn clean package就可以达到命令mvn clean package pluginA同样的效果了。更多信息可以搜索maven生命周期关键词了解,不再赘述。

3. 配置上传包的目标

上传目标就是要插件将打好的包上传到服务器,需要配置:

  1. 服务器地址
  2. 上传到的路径
  3. 要上传的包的路径

配置服务器相关信息的代码如下,在<execution>中加入<goals><configuration>标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<plugin>
...
<executions>
<execution>
...
<goals>
<!-- 上传一次 -->
<goal>upload-single</goal>
</goals>
<configuration>
<serverId>127.0.0.1</serverId>
<!-- 本地包位置 -->
<fromFile>target/my-war-package.war</fromFile>
<!-- 服务器用户、地址、存放路径 -->
<url>scp://root@127.0.0.1/root</url>
</configuration>
</execution>
</executions>
</plugin>

其中,

  • 标签<goals>表示目标,有多个目标时按照顺序执行,上传包使用upload-single即可,即上传一次。
  • 标签<configuration>表示服务器和上传路径配置

服务器和上传路径配置中,

  • 标签<serverId>即上面配置的服务器认证的id。
  • 标签<fromFile>表示打包后包的位置,一般都是target下的某个war包。
  • 标签<url>表示使用scp将包拷贝到指定的路径,root 是服务器用户名,**@** 后面是服务器地址和存放路径(类似scp命令)。

4. 配置执行部署脚本目标

执行部署脚本目标是当包上传完成后,用于在服务器执行部署脚本的。具体配置如下,在<goals>中加入<goal>,即加入新的目标,多个目标按顺序执行。以及在<configuration>标签中添加<commands><displayCommandOutputs>标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<execution>
...
<goals>
...
<!-- 加入执行脚本目标 -->
<goal>sshexec</goal>
</goals>
<configuration>
...
<!-- 执行命令行 -->
<commands>
<command>cd /root;./run.sh</command>
</commands>
<!-- 客户端打印命令和结果 -->
<displayCommandOutputs>true</displayCommandOutputs>
</configuration>
</execution>

其中,

  • 标签<goal> 表示执行ssh命令。
  • 标签<commands> 是要执行的命令行,具体命令在标签<command>中。案列中是进入war包所在目录,然后执行run.sh脚本。
  • 标签<displayCommandOutputs> 表示在客户端打印出执行的命令和命令返回结果。

需要注意的是,commond标签中的命令涉及到目录或文件需要使用全路径,如果不想使用全路径,可以像案列中那样,多条命令用分号隔开合并为一条语句,后面的命令就可以使用相对路径了。

编写部署脚本

这个步骤就是自定义部署的命令了,比如解压war包到目录,重启docker等,当然也可以不通过sh文件执行,也可以在commond标签中直接写命令,但是每一行命令都要使用完整路径,否则就使用案列中的一条语句,多条命令用分号隔开。下面是一个sh脚本示例。

1
2
3
date >> log.txt
ls my-war-package.war >> log.txt
echo deployed successfully >> log.txt

其他说明

wagon-maven-plugin版本说明

案列中采用的插件版本为2.0.0,如果使用1.0,还需要配置wagon-ssh,否则无法正常执行命令,会报错Cannot find wagon which supports the requested protocol: sftp: java.util.NoSuchElementException

1
2
3
4
5
6
7
8
9
10
<build>
...
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>3.3.3</version>
</extension>
</extensions>
</build>

多个阶段执行命令

案列中将插件配置在package阶段执行,即打包后执行上传和部署,如果在打包之前还要做一些准备工作,比如清理之前的包,关闭容器等,那么可以再配置一个执行(execution)并在clean阶段执行即可,具体代码如下,在id为upload-and-deploy这个执行之前再添加一个id为prepare的执行,就可以在clean之后,package之前执行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<plugin>
...
<executions>
<!-- 新增一个执行 -->
<execution>
<id>prepare</id>
<phase>clean</phase>
<goals>
<goal>sshexec</goal>
</goals>
<configuration>
<commands>
<!-- 执行准备工作的命令 -->
<command>cd /root;echo prepare > log.txt</command>
</commands>
<displayCommandOutputs>true</displayCommandOutputs>
</configuration>
</execution>

<!-- 和上面的案例一样 -->
<execution>
<id>upload-and-deploy</id>
...
</execution>
</executions>
</plugin>

FAQ

  • 报错Cannot connect. Reason: invalid privatekey

    错误原因是服务器认证没有配置或者配置不正确,配置方法见上述配置服务器认证

  • 报错Cannot find wagon which supports the requested protocol: sftp: java.util.NoSuchElementException

    错误原因是wagon-maven-plugin插件使用的1.0版本,并且没有配置wagon-ssh库,配置方法见上述wagon-maven-plugin版本说明

附件:配置代码

  • 服务器认证配置

    配置到maven的settints.xml中。

    1
    2
    3
    4
    5
    <server>
    <id>127.0.0.1</id>
    <username>root</username>
    <password>root</password>
    </server>
  • pom.xml配置

    配置到pom.xml的plugins标签中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>wagon-maven-plugin</artifactId>
    <version>2.0.0</version>
    <executions>
    <execution>
    <id>upload-and-deploy</id>
    <phase>package</phase>
    <goals>
    <goal>upload-single</goal>
    <goal>sshexec</goal>
    </goals>
    <configuration>
    <serverId>127.0.0.1</serverId>
    <fromFile>target/my-war-package.war</fromFile>
    <url>scp://root@127.0.0.1/root</url>
    <commands>
    <command>cd /root;./run.sh</command>
    </commands>
    <displayCommandOutputs>true</displayCommandOutputs>
    </configuration>
    </execution>
    </executions>
    </plugin>