以前作为后端,平时写好代码提交后就完事了,这周忽然叫我做公布到开发环境的操作,每次打包的复制到服务器上又很麻烦,尽管晓得Jenkins,然而这工具配置项也很多,就想着能不能自己做一个。于是就写起了代码。

想公布一个软件到服务器,先分步骤。

1.拉取代码

2.打包

3.复制到服务器

4.重启服务。

一开始,拉取代码的工作我是手动进行的,因为思考到要合并代码。这一步还是不要给程序做了,打包的话比较简单,间接

maven package

就好,顶多加一个

maven package -P dev(看你springboot里的配置)

打包完了必定要把包弄到服务器上,天然想到了scp命令,好在windows10是反对scp的,然而个别的scp须要明码,所以得把本人的公钥贴在服务器上。

登录到服务器

cd ~/.sshls显示出authorized_keys   id_rsa  id_rsa.pub  known_hosts把你windows的公钥追加到authorized_keys文件里就能够

于是我的第一个脚本是这样的

windows下新建bat

call "maven门路\mvn" package -P pro这里新建了脚本是因为maven运行完窗口不会主动敞开,没法执行下一行,新启脚本的话能够解决这个问题start /wait copy.bat

其中copy的bat是

scp C:\你的门路\你的我的项目.jar root@ip地址:/理论目录

看上去非常简单

把jar包拷贝过来了后怎么让他重启呢?

一开始想到用ssh近程执行命令,后果没找到不便又适合的计划,抉择了java解决。本人写了一个jar包当时丢上去。代码很简略

@Componentpublic class Task {    private String lastMd5 = "";    *//**     * 每隔20秒执行一次     *//*    @Scheduled(fixedRate = 20000)    public void testTasks() throws IOException {        String md5 = DigestUtils.md5DigestAsHex(new FileInputStream("你的服务器上包.jar"));        if(md5.equals(lastMd5)){            return;        }        System.out.println(md5);        lastMd5 = md5;        String[] cmd = new String[]{"/bin/sh", "-c", "ps -ef|grep 你的.jar |grep -v grep | awk '{print $2}' | xargs -r kill -9 &&  java -Dloader.path=/目录/lib -jar /你的服务器上包.jar"};        Process process = null;        try{             process = Runtime.getRuntime().exec(cmd);        }catch (Exception e){                    }    }}*/

首先阐明下,我maven打的是只蕴含class文件的包,不蕴含依赖的,所以一个包很小(不便传输和取md5)。

下面监听程序很简略,20秒跑一次,比照正在跑的jar包的md5(旧值)与传上去的jar包md5(新值),如果不一样就认为改变了,就调用bash脚本敞开原有的程序,而后重新启动程序。

到这里,我集体的主动部署曾经胜利了,每次拉取代码后想要更新,点一下bat,等几秒就行了。

共事看完感觉成果很不错,不过提了个倡议,你都上java了为什么不间接java把全副工作都做了,这语言咱们熟。

于是又进行了改版,找了下材料后,有了几个可用包。

1.JGIT(它的作用是拉取git代码)

<dependency>            <groupId>org.eclipse.jgit</groupId>            <artifactId>org.eclipse.jgit</artifactId>            <version>5.10.0.202012080955-r</version>        </dependency>
public class JgitUtil {    //验证    private static CredentialsProvider credentialsProvider;    //这个是我的项目拉取后的.git文件,用它来判断须要做git clone还是pull操作    private static String localGitUrl;    static {        credentialsProvider = new UsernamePasswordCredentialsProvider(PropUtils.get("username"), PropUtils.get("password"));        localGitUrl = System.getProperty("user.dir") + "/" + PropUtils.get("projectName") + "/.git";    }    /**     * git克隆     * @param gitUrl     * @param branch     * @throws GitAPIException     */    public static void gitClone(String gitUrl, String branch) throws GitAPIException {        Git.cloneRepository()                .setURI(gitUrl)                .setBranch(branch)                .setCredentialsProvider(credentialsProvider)                .setDirectory(new File(System.getProperty("user.dir") + "/" + PropUtils.get("projectName")))                .call();    }    /**     * git拉取操作     * @throws IOException     * @throws GitAPIException     */    public static void pull() throws IOException, GitAPIException {        //判断仓库是否曾经存在,不存在就clone        File local = new File(localGitUrl);        if(!local.exists()){            //第一个参数是git拉取的地址,第二个参数是分支名            gitClone(PropUtils.get("gitUrl"), PropUtils.get("branch"));            return;        }        //曾经存在就pull        Repository localRepo = new FileRepository(localGitUrl);        Git git = new Git(localRepo);        PullCommand pullCommand = git.pull();        pullCommand.setCredentialsProvider(credentialsProvider);        pullCommand.call();    }}

2.maven-invoker(它的作用是打包我的项目)

<dependency>            <groupId>org.apache.maven.shared</groupId>            <artifactId>maven-invoker</artifactId>            <version>3.1.0</version>        </dependency>
    private static InvocationRequest request;    private static Invoker invoker;    //须要设置maven目录    private static String mavenHome = System.getProperty("user.dir") + "/" + PropUtils.get("mavenName");    static {        request = new DefaultInvocationRequest();        //配置maven的settings.xml文件,外面仓库门路要配好        request.setUserSettingsFile(new File(mavenHome + "/conf/settings.xml"));        String env = PropUtils.get("env");        String packageStr = "package";        if(!StringUtils.isEmpty(env)){            packageStr += " -P " + env;        }        //这个设置maven命令,个别只用package        request.setGoals(Collections.singletonList(packageStr));                //设置我的项目的pom所在        File pomFile = new File(System.getProperty("user.dir") + "/" + PropUtils.get("projectName") + "/pom.xml");        if(!pomFile.exists()){            pomFile = new File(PropUtils.get("pomFile"));        }        request.setPomFile(pomFile);                //配置maven拉取的依赖所在的门路,我间接和maven放一起了        File repo = new File(mavenHome + "/repo");        if(!repo.exists()){            repo.mkdir();        }        request.setLocalRepositoryDirectory(repo);        invoker = new DefaultInvoker();        invoker.setMavenHome(new File(mavenHome));    }    //调用一下就能做拉取的操作    public static void mvnPackage() throws MavenInvocationException {        invoker.execute(request);    }

而后前端给个按钮,controller层就简略了

执行一下git拉取,执行一下maven打包

java用Runtime.getRuntime().exec(cmd)执行linux命令就能够了

linux命令包含杀死旧的java,命令在下面了, cp命令挪动打好的包,这里举荐用

/cp -ruv

后面带斜杠是要应用cp自身的命令,默认的cp命令有别名,理论调用的是cp -i,每次复制时会提醒要不要笼罩,加上斜杠就不会了。

复制好后重启jar包就能够了。

如果你想获取java调用linux命令后控制台的输入,能够这样

process = Runtime.getRuntime().exec(cmd);            LineNumberReader br = null;            br = new LineNumberReader(new InputStreamReader(                    process.getInputStream()));            StringBuffer sb = new StringBuffer();            String line;            while ((line = br.readLine()) != null) {                sb.append(line).append("\n");            }

但不是很举荐,打包命令很多无用的输入,这个是我以前写网页端调用linux命令时查的,这里其实不太用得上,不过我本人还是把cp后果打印到前端了,次要是看下是否胜利了。

前端成果,就两个按钮,一个公布后端,一个公布前端(这个做好了,暂无两个字忘了删了)。嫌麻烦能够间接用接口申请,post man或者window间接用curl,再写个bat(笑)

点个[公布前端],能够看到把cp命令打印进去了。