本实例为用Java执行shell脚本启动或关闭远程Mysql数据库,需求原因:游戏服务器合服后,为了节省内存消耗,需要关闭合服后的服务器不必要的数据库(一台服务器主机存在多个MySql数据库),以提高服务器性能,但有时需要查询历史游戏玩家信息,又需要开启数据库,为了节省运维人员的人力和时间,游戏后台就提供非运维人员都可操作开关数据库的操作。
功能实现步骤:
第一:服务器后台提供参数,发送异步请求,请求方法如下
<script type="text/javascript">
function shutdownDatabase(param,operate){
var arr=param.replace(/\s+/g," ").split(" ");
if(arr.length!=3){
alert("数据库脚本参数个数不正确,请编辑好再操作!");
return false;
}
param = param + " " + operate;
$.ajax({
url:'XXXAction!databaseSwitch.action',
type:"post",
data:{"param":param},
dataType:"json",
async:true,
success:function(data){
$("#progressImgage").hide();//进度条隐藏
$("#maskOfProgressImage").hide();//蒙版隐藏
alert("执行结果:"+data.result);
},
error:function(data){
$("#progressImgage").hide();
$("#maskOfProgressImage").hide();
alert("执行结果:"+data.result);
},
beforeSend:function(xhr){
$("#progressImgage").show().css({
"position": "fixed",
"top": "50%",
"left": "50%",
"margin-top": function () { return -1 * $("#progressImgage").height() / 2; },
"margin-left": function () { return -1 * $("#progressImgage").width() / 2; }
});
$("#maskOfProgressImage").show().css("opacity", "0.1");
}
});
}
</script>
其中param为shell脚本参数,根据具体业务而不同。
请求等待提示代码
<img id="progressImgage" class="progress hide" alt="数据库操作中" src="./images/loading.jpg" width="250" height="200"/>
<div id="maskOfProgressImage" class="mask hide"></div>
<style type="text/css">
.hide{display:none }
.progress{z-index: 2000}
.mask{position: fixed;top: 0;right: 0;bottom: 0;left: 0; z-index: 1000; background-color: #000000}
</style>
第二,后台java代码,发送异步请求到后台java方法,java方法操作执行shell脚本,执行代码如下
/**
* 服务器数据库开关
*/
public void databaseSwitch() {
logger.info("服务器数据库开关 start");
PrintWriter out = null;
try {
ActionContext context = ActionContext.getContext();
HttpServletRequest request = (HttpServletRequest)context.get(ServletActionContext.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse)context.get(ServletActionContext.HTTP_RESPONSE);
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
out= getServletResponse().getWriter();
String param= request.getParameter("param");
if (null == param || "".equals(param)) {
out.write("{\"result\":\"脚本参数不能为空"+"\"}");
return;
}
String shellStr = "sh /data0/mysql_actions.sh "+param;
logger.info("执行脚本:"+shellStr);
List<String> result = new ArrayList<String>();
result = execShell(shellStr);
out.write("{\"result\":\""+result.toString()+"\"}");
logger.info("执行结果:"+result);
} catch (UnsupportedEncodingException e1) {
out.write("{\"result\":\"操作数据库时不支持字符编码出错!\"}");
logger.error("execShell方法异常"+e1);
e1.printStackTrace();
} catch (Exception e) {
out.write("{\"result\":\"操作数据库出错!\"}");
logger.error("execShell方法异常");
e.printStackTrace();
}
logger.info("服务器数据库开关 end");
}
/**
* 运行shell
* @param shStr
* 需要执行的shell
* @return
* @throws IOException
*/
public static List<String> execShell(String shStr) throws Exception {
List<String> strList = new ArrayList<String>();
Process process;
process = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c",shStr},null,null); 执行shell命令
InputStreamReader ir = new InputStreamReader(process.getInputStream());
LineNumberReader input = new LineNumberReader(ir); //脚本输出
String line;
int extValue = process.waitFor(); //执行结果
strList.add("extValue="+extValue);
while ((line = input.readLine()) != null){
strList.add(line);
}
process.destroy();//杀掉进程
return strList;
}
执行脚本的主要方法为:execShell(String shStr),其中shStr参数为要执行的shell脚本,本实例的脚本写成文件直接调用,这样可读性,可移植性强。
第三,关闭远程服务器数据库
主要是在shell脚本中通过ssh,连接远程服务器,通过脚本判断数据库是否开启并执行开关操作,最后返回结果
关键代码为:
ssh="ssh -c arcfour128 -o MACs=umac-64@openssh.com -o StrictHostKeyChecking=no -o GSSAPIAuthentication=no -p 22"
$ssh $1 "ps -ef |grep mysql |grep \`cat /data/${3}/mysql/port\`" &> /dev/null
if [ $? -eq 0 ];then
echo "主库目前已经处于运行状态"
else
$ssh $1 "sh /data0/${3}/mysql/start-mysql.sh &> /dev/null"
if [ $? -eq 0 ];then
echo "成功开启主库"
else
echo "开启主库失败"
fi
fi
其中$1参数为远程服务器ip
详细代码就不贴出来了,详解请私信我。这个功能做出来是非常耗时的,但做出来后,别人就很省时了,含金量比较大。
如果脚本不熟,需要运维人员提供。一个人写需要懂的技术很多,深度很深。
问题1:我执行脚本期间遇到一个问题就是没有在root用户下执行,导致失败,执行脚本需在管理员权限下执行才能成功。
问题2:后台需要远程服务器的无密码登录权限,通过key设置,ssh还要设置为“ForwardAgent yes”。
一切就绪后台即可执行,祝读者好运!