以前作为后端,平时写好代码提交后就完事了,这周忽然叫我做公布到开发环境的操作,每次打包的复制到服务器上又很麻烦,尽管晓得 Jenkins,然而这工具配置项也很多,就想着能不能自己做一个。于是就写起了代码。
想公布一个软件到服务器,先分步骤。
1. 拉取代码
2. 打包
3. 复制到服务器
4. 重启服务。
一开始,拉取代码的工作我是手动进行的,因为思考到要合并代码。这一步还是不要给程序做了,打包的话比较简单,间接
maven package
就好,顶多加一个
maven package -P dev(看你 springboot 里的配置)
打包完了必定要把包弄到服务器上,天然想到了 scp 命令,好在 windows10 是反对 scp 的,然而个别的 scp 须要明码,所以得把本人的公钥贴在服务器上。
登录到服务器
cd ~/.ssh
ls 显示出
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 包当时丢上去。代码很简略
@Component
public 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 命令打印进去了。