Linux机器上实现程序自动部署以及更新

平台化管理Linux环境的客户端程序的部署、更新、以及进程关闭

 

平台是用SSH实现,前端是avalon,数据库mysql客户端程序(Monitor, CLientSetup)是spring boot实现平台操作界面如下:

客户端程序访问路径为 http://ip:8034, 

获取版本方式为 http://ip:8034/Deploy/Version

心跳地址为 http://ip:8034/Deploy/ReturnOk

1. 更新状态访问版本地址,返回该ip对应的版本,落入数据库,更新页面信息

2. 部署以及更新应用所有服务器路径都在ftpuser用户目录下,即/STRESS

应用源码放在服务器A上,为Monitor.tar,上传脚本Deploy.sh也在服务器A上,

上传脚本如下:

IP=$1

echo "put tar to "${IP}
ftp -n<<!
open ${IP}
user ftpuser ******
binary
prompt
mkdir tools
cd tools
put Monitor.tar
put ClientSetup.tar
put clientDeploy.sh
#chmod 777 clientDeploy.sh
close
bye
!

  

平台调用上传脚本把源码从服务器A传到目标服务器B上。

平台再调用服务器B上脚本tools/clientDeploy.sh

cd tools
rm -rf Monitor
rm -rf ClientSetup
tar -xvf Monitor.tar
tar -xvf ClientSetup.tar
cd ~/tools/Monitor
sh restart.sh
cd ~/tools/ClientSetup
sh restart.sh
cd ~/tools
rm -rf Monitor.tar
rm -rf ClientSetup.tar

  

平台调用Java代码

public String DeployEnvAgency(String ip) throws IOException, InterruptedException
{
RemoteShellTool tool = new RemoteShellTool("172.16.103.126", "ftpuser", 
"88888", "utf-8"); 

String result = tool.exec("sh Deploy.sh "+ip); 
System.out.print("result:"+result); 

RemoteShellTool tool2 = new RemoteShellTool(ip, "ftpuser", 
"******", "utf-8"); 

String result2 = tool2.exec("sh tools/clientDeploy.sh"); 
System.out.print("result2:"+result2); 

return "ok";
}

  

3. 关闭进程
java代码:

public String killClient(String ip) throws IOException, InterruptedException
{
RemoteShellTool tool = new RemoteShellTool(ip,"utf-8");
tool.loginCentos();
tool.exec("kill -9 $(ps -ef|grep ClientSetup|gawk '$0 !~/grep/ {print $2}'|tr -s '
''')"); 
tool.exec("kill -9 $(ps -ef|grep SpringMVCDemo|gawk '$0 !~/grep/ {print $2}'|tr -s '
''')"); 

return "ok";
}

调用RemoteShellTool类如下:

package com.ymt.testplatform.util;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;

public class RemoteShellTool {
private Connection conn; 
private String ipAddr; 
private String charset = Charset.defaultCharset().toString(); 
private String userName; 
private String password; 

public RemoteShellTool(String ipAddr, String charset) { 
this.ipAddr = ipAddr; 
if (charset != null) { 
this.charset = charset; 
} 
} 

public RemoteShellTool(String ipAddr, String userName, String password, 
String charset) { 
this.ipAddr = ipAddr; 
this.userName = userName; 
this.password = password; 
if (charset != null) { 
this.charset = charset; 
} 
} 

public boolean login() throws IOException { 
conn = new Connection(ipAddr); 
conn.connect(); // 连接 
return conn.authenticateWithPassword(userName, password); // 认证 
} 

public boolean loginCentos() throws IOException
{
conn = new Connection(ipAddr); 
conn.connect(); // 连接 

String [] pass = {"ymt@123","abcd@1234","root@1234","******","1234qwer"};

for (String pa : pass) {
if(conn.authenticateWithPassword("root", pa))
{
this.userName = "root"; 
this.password = pa; 
return true;
}
}	

return false;

}

public boolean login(String userName,String password) throws IOException { 
conn = new Connection(ipAddr); 
conn.connect(); // 连接 
this.userName = userName; 
this.password = password; 
return conn.authenticateWithPassword(userName, password); // 认证 
} 

public String exec(String cmds) { 
InputStream in = null; 
String result = ""; 
try { 
if (this.login()) { 
Session session = conn.openSession(); // 打开一个会话 
session.execCommand(cmds); 

in = session.getStdout(); 
result = this.processStdout(in, this.charset); 
session.close(); 
conn.close(); 
} 
} catch (IOException e1) { 
e1.printStackTrace(); 
} 
return result; 
} 

public String processStdout(InputStream in, String charset) { 

byte[] buf = new byte[1024]; 
StringBuffer sb = new StringBuffer(); 
try { 
while (in.read(buf) != -1) { 
sb.append(new String(buf, charset)); 
} 
} catch (IOException e) { 
e.printStackTrace(); 
} 
return sb.toString(); 
} 

/** 
* @param args 
*/ 
public static void main(String[] args) { 

RemoteShellTool tool = new RemoteShellTool("172.16.103.126", "ftpuser", 
"******", "utf-8"); 

String result = tool.exec("sh Deploy.sh 172.16.103.121"); 
System.out.print("result:"+result); 

RemoteShellTool tool2 = new RemoteShellTool("172.16.103.121", "ftpuser", 
"******", "utf-8"); 

String result2 = tool2.exec("sh tools/clientDeploy.sh"); 
System.out.print("result2:"+result2); 

} 

}

  

 附
html

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <link href="/css/reset.css" rel="stylesheet">
    <link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <link href="/css/admin/layout.css" rel="stylesheet">
    <link href="/css/admin/envinfo.css" rel="stylesheet">
    <script type="text/javascript" src="/lib/jquery.js"></script>
    <script type="text/javascript" src="/bootstrap/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="/bootstrap/js/jquery.bootpag.min.js"></script>
    <script type="text/javascript" src="/lib/avalon.js"></script>
    <script type="text/javascript" src="/js/common/util.js"></script>
    <script type="text/javascript" src="/js/admin/common/common.js"></script>
    <script type="text/javascript" src="/js/admin/monitordeploy.js"></script>

    <title>基础信息管理</title>
</head>

<body ms-controller="vm">
    <!-- ADMIN HEAD -->
    <div ms-include-src="'/admin/header.html'"></div>
    <!-- Content -->
    <div class="container">
        <div ms-controller="monitordeploy">
            <div class="tabbable">
                
                <div class="tab-content">
                    <div class="tab-pane active" id="vms">
                        <div id="vmsTab-pane">
                            <br/>
                            <div class="row" id="search1Div">
                                <div class="col-md-2">
                                    <div class="input-group">
                                        <span class="input-group-addon">环境:</span>
                                        <select class="form-control" ms-duplex="envType">
                                            <option value="STRESS" selected>STRESS</option>
                                            <option value="ALL">全部</option>
                                            <option value="SIT1">SIT1</option>
                                            <option value="SIT2">SIT2</option>
                                            <option value="UAT">UAT</option>
                                            <option value="other">其他</option>
                                        </select>
                                    </div>
                                </div>
                            <div class="row" id="search2Div">
                                <div class="col-md-2">
                                    <div class="input-group">
                                        <span class="input-group-addon">类型:</span>
                                        <select class="form-control" ms-duplex="conType">
                                            <option value="" selected>请选择</option>
                                            <option value=".Net Web">.Net Web</option>
                                            <option value="Windows Service">Windows Service</option>
                                            <option value="Node">Node</option>
                                            <option value="Java App">Java App</option>
                                            <option value="Java Web">Java Web</option>
                                            <option value="其他">其他</option>
                                        </select>
                                    </div>
                                </div>
                                <div class="col-md-1">
                                    <button type="button" id="searchBtn" class="btn btn-primary" ms-click="listVmInfosByPage('init')" style="margin: auto;">
                                       	搜 索
                                    </button>
                                </div>
                               
                                 <div class="col-md-1">
                                    <button type="button" id="allCheckBtn" class="btn btn-info" ms-click="checkAll()" style="margin: auto;">
                                       	全选
                                    </button>
                                </div>
                                
                                <div class="col-md-1">
                                    <button type="button" id="allUncheckBtn" class="btn btn-info" ms-click="uncheckAll()" style="margin: auto;">
                                       	全不选
                                    </button>
                                </div>
                                
                                 <div class="col-md-1">
                                    <button type="button" id="allStatusBtn" class="btn btn-success" ms-click="viewAllStatus()" style="margin: auto;">
                                       	update all
                                    </button>
                                </div>
                                
                                 <div class="col-md-1">
                                    <button type="button" id="allDeployBtn" class="btn btn-warning" ms-click="deployAll()" style="margin: auto;">
                                       	deploy all
                                    </button>
                                </div>
                                 
                                <div class="col-md-1">
                                    <button type="button" id="allDeployBtn" class="btn btn-danger" ms-click="killAll()" style="margin: auto;">
                                       	kill all
                                    </button>
                                </div>
                              
                            </div>
                            
                      
                            <div>
                                <div id="pageSizeSelect"><a><span ms-class="{{pagesize1Cls}}"
                                              ms-click="changePageSize(pagesize1)">{{pagesize1}}</span></a> | <a><span
                    ms-class="{{pagesize2Cls}}" ms-click="changePageSize(pagesize2)">{{pagesize2}}</span></a> |
                                    <a>
                                        <spam ms-class="{{pagesize3Cls}}" ms-click="changePageSize(pagesize3)">{{pagesize3}}</spam>
                                    </a>
                                </div>
                            </div>
                            <table class="table table-condensed table-hover">
                                <thead>
                                    <tr>
                                   		<td class="width-50"></td>
                                        <td class="width-50">ID</td>
                                        <td>名称</td>
                                        <td class="width-125">IP</td>
                                        <td class="width-300">操作系统</td>
                                        
                                        <td class="width-100">监控版本</td>
                                        <td class="width-100">Setup版本</td>
                                        <td class="width-100">监控状态</td>
                                        <td class="width-100">Setup状态</td>
                                        <td class="width-100">更新时间</td>
                                        <td class="width-50">状态更新</td>
                                        <td class="width-50">部署</td>
                                         <td class="width-50">kill</td>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr ms-repeat="vmsList">
                                   		<td><label><input type="checkbox" ms-class="check_{{el.name}}" ></label></td>
                                        <td>{{$index+jpageSize*(jpageIndex-1)+1}}</td>
                                        <td>{{el.name}}</td>
                                        <td><a ms-href="'/admin/vmdetails.html?vmid='+el.vm.id" target="_blank">{{el.ip}}</a></td>
                                        <td>{{el.os}}</td>                                     
                                        <td>{{el.version}}</td>
                                        <td>{{el.setupVersion}}</td>
                                        <td>{{el.clientOn}}</td>
                                        <td>{{el.setupOn}}</td>
                                        <td>{{el.time}}</td>
                                        <td>
                                         <div ms-class="buttonDiv_view_{{el.name}}">
                                            <i style="color:#009100;" ms-class="glyphicon glyphicon-eye-open icon-white i_view_{{el.name}}"  ms-click="postViewStatus(el.name,el.ClientOn,el.SetupOn,el.ip)"></i>
                                         </div> 
                                         <div ms-class="loadDiv_view_{{el.name}} loadDiv"  style="display:none">	
                                         	<img src="/img/load2.jpg" style="16px;height:16px;"/>
                                         </div> 
                                        </td>
                                         <td>
                                         <div ms-class="buttonDiv_{{el.name}}">
                                            <i style="color:#000066;" ms-class="glyphicon glyphicon-play icon-white i_{{el.name}}" ms-click="postDeploy(el.name,el.ip,el.os)"> </i>
                                         </div> 
                                         <div ms-class="loadDiv_{{el.name}} loadDiv"  style="display:none">	
                                         	<img src="/img/load2.jpg" style="16px;height:16px;"/>
                                         </div> 
                                          
                                        </td>
                                        <td>
                                         <div ms-class="buttonDiv_kill_{{el.name}}">
                                            <i style="color:#CE0000;" ms-class="glyphicon glyphicon-remove icon-white ikill_{{el.name}}" ms-click="postkill(el.name,el.ip,el.os)"> </i>
                                         </div> 
                                         <div ms-class="loadDiv_kill_{{el.name}} loadDiv"  style="display:none">	
                                         	<img src="/img/load2.jpg" style="16px;height:16px;"/>
                                         </div> 
                                          
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                            <div class="text-center">
                                <p id="pagination"></p>
                            </div>
                        </div>
                    </div>
                   
               
            </div>
        </div>

    </div>
</div>
<!-- /.container-->

</body>
</html>

  js

/**
 * Created by chenjiazhu on 2017/2/15.
 */
var monitordeploy = avalon.define({
    $id: 'monitordeploy',
   
    //VM Start
    pagesize1: "20",
    pagesize1Cls: "pageSizeSelected",
    pagesize2: "50",
    pagesize2Cls: "",
    pagesize3: "100",
    pagesize3Cls: "",
    changePageSize: function(pgsize) {
        monitordeploy.jpageSize = pgsize;
        monitordeploy.listVmInfosByPage("init");
    },
    clearsearch: function() {
        monitordeploy.conType = "";
        monitordeploy.listVmInfosByPage("init");
    },
    jpageIndex: 1,
    jpageSize: 20,
    envType: "STRESS",
    conType: "",
    
    vmsList: [],
    
    listVmInfosByPage: function(tag) {
        if (tag) {
            monitordeploy.jpageIndex = 1;
        }
        $.ajax({
            type: "post",
            url: 'listDeployVmInfosByPageByEnvType.action',
            data: {
                "pageindex": monitordeploy.jpageIndex,
                "pagesize": monitordeploy.jpageSize,
                "type": monitordeploy.conType,
                "envType": monitordeploy.envType
            },
            dataType: "json",
            success: function(data) {
                if (tag) {
                    $('#pagination').bootpag({
                        total: data.pagenum,
                        page: monitordeploy.jpageIndex
                    });
                }
                if (data.retCode == "1000") {
                    monitordeploy.vmsList = data.vms;
                } else {
                    alert(data.retMSG);
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("请求数据异常,状态码:" + XMLHttpRequest.status+",Error:"+errorThrown+",textStatus:"+textStatus);
            }
        });
    },
    
    postViewStatus: function(name, status1,status2,ip) {
       if(status1==null || status1=="")
       {
    	   status1=0;
       }
       
       if(status2==null || status2=="")
       {
    	   status2=0;
       }
       
       $(".loadDiv_view_"+name).show();
       $(".buttonDiv_view_"+name).hide();
       
       // 检查Monitor状态    	
    	$.ajax({
            type: "GET",
            dataType : 'jsonp',  
            jsonp:"jsoncallback",  
            url: "http://"+ip+":8034/Deploy/ReturnOk",

            success: function (data) {
            	  if(data.data=="ok")
  			    {
  			    	if(status1!="ok")
  			    	{
  			    		monitordeploy.updateMonitorStatus(ip,"ok");
  			    	}
  			    }
  			    else
  			    {
  			    	if(status1!="fail")
  			    	{
  			    		monitordeploy.updateMonitorStatus(ip,"fail");
  			    	}
  			    }
            	  
            	  $(".loadDiv_view_"+name).hide();
                  $(".buttonDiv_view_"+name).show();
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("请求数据异常,状态码:" + XMLHttpRequest.status+",Error:"+errorThrown+",textStatus:"+textStatus);
                $(".loadDiv_view_"+name).hide();
                $(".buttonDiv_view_"+name).show();
            }
        });
    	
    	// 检查ClientSetup状态    	
    	$.ajax({
            type: "GET",
            dataType : 'jsonp',  
            jsonp:"jsoncallback",  
            url: "http://"+ip+":8035/Deploy/ReturnOk",

            success: function (data) {
            	if(data.data="ok")
  			    {
  			    	if(status1!="ok")
  			    	{
  			    		monitordeploy.updateClientSetupStatus(ip,"ok");
  			    	}
  			    }
  			    else
  			    {
  			    	if(status1!="fail")
  			    	{
  			    		monitordeploy.updateClientSetupStatus(ip,"fail");
  			    	}
  			    }
            	
            	 
            	$(".loadDiv_view_"+name).hide();
                $(".buttonDiv_view_"+name).show();
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("请求数据异常,状态码:" + XMLHttpRequest.status+",Error:"+errorThrown+",textStatus:"+textStatus);
                
                $(".loadDiv_view_"+name).hide();
                $(".buttonDiv_view_"+name).show();
            }
        });
    },
    
    updateMonitorStatus: function(ip,status) {
        
        $.ajax({
            type: "post",
            url: 'updateMonitorStatus.action',
            data: {
                "ip": ip,
                "status1": status,
            },
            dataType: "json",
            success: function(data) {
               
                if (data.retCode != "1000") {
                	 alert("更新"+ip+"Monitor状态失败!");
                } 
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("请求数据异常,状态码:" + XMLHttpRequest.status+ ",<br/>"+XMLHttpRequest.readyState+  ",<br/>"+XMLHttpRequest.responseText+",<br/>Error:"+errorThrown+",<br/>textStatus:"+textStatus);
            }
        });
    },
    
    updateClientSetupStatus: function(ip,status) {
        
        $.ajax({
            type: "post",
            url: 'updateClientSetupStatus.action',
            data: {
                "ip": ip,
                "status2": status,
            },
            dataType: "json",
            success: function(data) {
               
                if (data.retCode != "1000") {
                	 alert("更新"+ip+"ClientSetupStatus!");
                } 
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("请求数据异常,状态码:" + XMLHttpRequest.status+ ",<br/>"+XMLHttpRequest.readyState+  ",<br/>"+XMLHttpRequest.responseText+",<br/>Error:"+errorThrown+",<br/>textStatus:"+textStatus);
            }
        });
    },
    
    postDeploy: function(name,ip,os) {
        
        $(".loadDiv_"+name).show();
        $(".buttonDiv_"+name).hide();
        
        $.ajax({
            type: "post",
            url: 'deploy.action',
            data: {
                "ip": ip,
                "os": os
            },
            dataType: "json",
            success: function(data) {
            	$(".loadDiv_"+name).hide();
                $(".buttonDiv_"+name).show();
                
            	if(data.data=="false")
 			    {
 			    	alert("更新"+ip+"客户端失败!");
 			    } 
            	else
            		{
            		monitordeploy.listVmInfosByPage();
            		}
            	
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
            	$(".loadDiv_"+name).hide();
	            $(".buttonDiv_"+name).show();
                alert("请求数据异常,状态码:" + XMLHttpRequest.status+ ",<br/>"+XMLHttpRequest.readyState+  ",<br/>"+XMLHttpRequest.responseText+",<br/>Error:"+errorThrown+",<br/>textStatus:"+textStatus);
            }
        });
     },
     
     postkill: function(name,ip,os) {
         
         $(".loadDiv_kill_"+name).show();
         $(".buttonDiv_kill_"+name).hide();
         
         $.ajax({
             type: "post",
             url: 'kill.action',
             data: {
                 "ip": ip,
                 "os": os
             },
             dataType: "json",
             success: function(data) {
             	$(".loadDiv_kill_"+name).hide();
                 $(".buttonDiv_kill_"+name).show();
                 
             	if(data.data=="false")
  			    {
  			    	alert("杀死"+ip+"监控进程失败!");
  			    } 
             	             	
             },
             error: function (XMLHttpRequest, textStatus, errorThrown) {
             	$(".loadDiv_kill_"+name).hide();
 	            $(".buttonDiv_kill_"+name).show();
                 alert("请求数据异常,状态码:" + XMLHttpRequest.status+ ",<br/>"+XMLHttpRequest.readyState+  ",<br/>"+XMLHttpRequest.responseText+",<br/>Error:"+errorThrown+",<br/>textStatus:"+textStatus);
             }
         });
      },
     
     viewAllStatus:function() {
    	 $("input[type='checkbox']").each(
    			 function(){
    				 if($(this).get(0).checked)
    					 {
    					
    					 var name = $(this).attr("class").substr(6);
    					 //alert(name);
    					 $(".i_view_"+name).click();
    					 }
    				 
    			 }
    	 );
     },
     
     deployAll:function() {
    	 $("input[type='checkbox']").each(
    			 function(){
    				 if($(this).get(0).checked)
    					 {
    					
    					 var name = $(this).attr("class").substr(6);
    					 //alert(name);
    					 $(".i_"+name).click();
    					 }
    				 
    			 }
    	 );
     },
     
     killAll:function() {
    	 $("input[type='checkbox']").each(
    			 function(){
    				 if($(this).get(0).checked)
    					 {
    					
    					 var name = $(this).attr("class").substr(6);
    					 //alert(name);
    					 $(".ikill_"+name).click();
    					 }
    				 
    			 }
    	 );
     },
     
    checkAll:function(){
    	$("input[type='checkbox']").each(
   			 function(){
   				 $(this).attr("checked","true");  
   			 }
   	 );
    },
    
    uncheckAll:function(){
    	 $("input[type='checkbox']").each(
    			 function(){
    				 $(this).removeAttr("checked"); 
    			 }
    	 );
    },
    
    loadVmTAB: function() {
        monitordeploy.listVmInfosByPage("init");
        $('#vms').tab('show');
    },
    //VM END
    userOps: ops(4),
    bootpagFuc: function() {
    	 
        $('#pagination').bootpag({
            total: 1,
            maxVisible: 10
        }).on('page', function(event, num) {
            monitordeploy.jpageIndex = num;
            monitordeploy.listVmInfosByPage();
        });
    }
});

avalon.ready(function() {
    if (monitordeploy.userOps) {
        monitordeploy.loadVmTAB();
       
    } else {
        redirectAdminIndexPage();
    }
    monitordeploy.bootpagFuc();
//    $(".loadDiv").hide();
});


monitordeploy.$watch("jpageSize", function(newValue) {
    monitordeploy.pagesize1Cls = "";
    monitordeploy.pagesize2Cls = "";
    monitordeploy.pagesize3Cls = "";
    if (newValue == monitordeploy.pagesize1) {
        monitordeploy.pagesize1Cls = "pageSizeSelected";
    } else if (newValue == monitordeploy.pagesize2) {
        monitordeploy.pagesize2Cls = "pageSizeSelected";
    } else if (newValue == monitordeploy.pagesize3) {
        monitordeploy.pagesize3Cls = "pageSizeSelected";
    }
})

  

 
原文地址:https://www.cnblogs.com/chenjiazhu/p/7423680.html