一、背景
马上过五一了,为了应对线上服务宕机,领导安排每个人轮流值班。但是服务器部署在内网,即使知道宕机了,想要重启,没有电脑是不行的。这对于五一出去旅行的我们,带电脑出行是不可行的。所以想到在服务器启动一个服务,通过nginx外网映射出来,然后通过手机访问h5页面,调用后台java程序,执行提前写好的服务重启脚本,搞定。废话不多说,开始:
二、程序采用h5 + bootstrap+springBoot完成。
- 前端页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css"></link>
<script th:src="@{/md5.js}"></script>
</head>
<body class="container">
<div style="margin-top: 100px;">
<label>test操作</label>
<button type="button" class="btn btn-danger" onclick="execShell('test_stop')">停止test</button>
<button type="button" class="btn btn-success" onclick="execShell('test_start')">启动test</button>
</div>
<div style="margin-top: 20px;">
<label>8082操作</label>
<button type="button" class="btn btn-danger" onclick="execShell('8081_stop')">停止8081</button>
<button type="button" class="btn btn-success" onclick="execShell('8081_start')">启动8081</button>
</div>
<div style="margin-top: 20px;">
<label>8082操作</label>
<button type="button" class="btn btn-danger" onclick="execShell('8082_stop')">停止8082</button>
<button type="button" class="btn btn-success" onclick="execShell('8082_start')">启动8082</button>
</div>
<div style="margin-top: 20px;">
<label>请输入校验码:</label><input class="form-control" type="password" id="password"/>
</div>
<script>
function execShell(flag) {
var comfigMsg = "";
if ("test_stop"==flag) {
comfigMsg="确定停止测试服务?"
} else if ("test_start"==flag) {
comfigMsg="确定重启测试服务?"
} else if ("8081_stop"==flag) {
comfigMsg="确定停止 8081 服务?"
} else if ("8081_start"==flag) {
comfigMsg="确定重启 8081 服务?"
} else if ("8082_stop"==flag) {
comfigMsg="确定停止 8082 服务?"
} else if ("8082_start"==flag) {
comfigMsg="确定重启 8082 服务?"
}
if(window.confirm(comfigMsg)){
console.log("确定");
}else{
console.log("取消");
return false;
}
//创建异步对象
var xhr = new XMLHttpRequest();
//设置请求的类型及url
//post请求一定要添加请求头才行不然会报错
xhr.open('post', '/bash/execShell');
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//发送请求
var password = document.getElementById("password").value;
var md5Password = hex_md5(password);//md5加密,md5.js自行在网上下载
xhr.send('flag=' + flag + "&password=" + md5Password);
xhr.onreadystatechange = function () {
// 这步为判断服务器是否正确响应
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
alert(xhr.responseText);
}
};
}
</script>
</body>
</html>
- 后台java代码
package com.nansw.bash;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
@Controller
public class BashController {
private String key = "hello123!@#";
@RequestMapping("/shell")
public String shell(HttpServletRequest request, Model model) {
String rootPath = request.getContextPath();
model.addAttribute("ctx", rootPath);
return "shell/shell";
}
@ResponseBody
@RequestMapping("/execShell")
public String execShell(String flag, String password) {
String message = "执行成功";
System.out.println("执行标志:" + flag);
if (!Md5Utils.string2MD5(key).equals(password)) {
message = "密码错误";
System.out.println(message + ":" + flag);
return message;
}
try {
String shpath = "";
if ("test_stop".equals(flag)) {
shpath = "/home/apache-test/bin/stop.sh";
} else if ("test_start".equals(flag)) {
shpath = "/home/apache-test/startup.sh";
} else if ("8081_stop".equals(flag)) {
shpath = "/home/apache-8081/bin/stop.sh";
} else if ("8081_start".equals(flag)) {
shpath = "/home/apache-8081/bin/startup.sh";
} else if ("8082_stop".equals(flag)) {
shpath = "/home/apache-8082/bin/stop.sh";
} else if ("8082_start".equals(flag)) {
shpath = "/home/apache-8082/bin/startup.sh";
} else {
message = "不识别的标志";
System.out.println(message + ":" + flag);
return message;
}
shpath = "/bin/sh " + shpath;
System.out.println("即将执行脚本:" + shpath);
Process ps = Runtime.getRuntime().exec(shpath);
ps.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
String result = sb.toString();
System.out.println(result);
message = result;
} catch (Exception e) {
e.printStackTrace();
message = e.getMessage();
}
return message;
}
}
- MD5Utils.java
package com.nansw.bash;
import java.security.MessageDigest;
public class Md5Utils {
/***
* MD5加码 生成32位md5码
*/
public static String string2MD5(String inStr){
MessageDigest md5 = null;
try{
md5 = MessageDigest.getInstance("MD5");
}catch (Exception e){
System.out.println(e.toString());
e.printStackTrace();
return "";
}
char[] charArray = inStr.toCharArray();
byte[] byteArray = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++)
byteArray[i] = (byte) charArray[i];
byte[] md5Bytes = md5.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++){
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16)
hexValue.append("0");
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
public static void main(String[] args) {
System.out.println(string2MD5("123456"));
}
}
- stop.sh 杀死进程的脚本
#!/bin/sh
pid=$(ps -ef | grep "/home/apache-test" | grep -v grep | awk '{print $2}')
echo $pid
kill -9 $pid
-
startup.sh 即tomcat自带的启动文件
-
运行效果