天天看点

补丁更新

package com.suteam.zsyun.job;

import java.io.BufferedReader;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.net.HttpURLConnection;

import java.net.URL;

import java.security.MessageDigest;

import java.util.HashMap;

import java.util.Map;

import java.util.Properties;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;

import com.suteam.zsyun.application.model.ApplicationFilePack;

import com.suteam.zsyun.commonUtil.FileUtil;

import com.suteam.zsyun.commonUtil.HttpAuthUtil;

import com.suteam.zsyun.commonUtil.ModifyConfig;

import com.suteam.zsyun.config.Config;

public class BasicJobUtil {

    public static Logger log = Logger.getLogger(BasicJobUtil.class);

    public static void executeTask() {

        log.info(" *****agent守护进程定时任务开始***** ");

        try {

            // 获取jar文件当前路径

            String path = System.getProperty("user.dir");

            log.info("jar文件当前路径:"+path);

            // 获取配置文件路径

            String configPath = FileUtil.getConfigPath();

            // 读取配置文件config.ini,获取版本号version_Number与当前jar文件名称

            Properties configProperty = FileUtil.getConfig(configPath + Config.configName);

            String versionNumber = configProperty.getProperty("version_Number");

            String agentName = configProperty.getProperty("agent_Name");

            // 读取配置文件es.ini,获取code

            Properties esProperty = FileUtil.getConfig(configPath + Config.esName);

            String code = esProperty.getProperty("code");

            // 读取配置文件watch.ini,获取app项目服务器地址

            Properties watchProperty = FileUtil.getConfig(configPath + Config.watchName);

            String appServer = watchProperty.getProperty("appServer");

            // 声明一个存放请求参数的map

            Map<String, String> parameterMap = new HashMap<String, String>();

            // 拼接调用app项目中的版本查询接口的url和参数

            String url = appServer + "/v1/port/appService/query/queryPatch.do";

            parameterMap.put("code", code);

            parameterMap.put("versionNumber", versionNumber);

            // 调用APP项目中版本查询接口

            log.info("调用APP项目中版本查询接口:");

            String result = HttpAuthUtil.doAuthPost(url, parameterMap);

            Map<String, Object> mapResult = (Map<String, Object>) JSON.parse(result);

            if (null != mapResult && "ok".equals(mapResult.get("result"))) {

                log.info("调用APP项目中版本查询接口,ok:");

                // 解析获取应用文件包对象

                ApplicationFilePack applicationFilePack = JSON.parseObject(String.valueOf(mapResult.get("values")),

                        ApplicationFilePack.class);

                // 判断应用文件包对象是否为空。不为空说明有要更新的agent。

                if (null != applicationFilePack) {

                    log.info("文件包对象不为空,说明有要更新的agent。");

                    // 获取版本

                    String version = applicationFilePack.getVersion();

                    log.info("获取新版本version:" + version);

                    if (!version.equals(versionNumber)) {

                        log.info("新旧版本不同。");

                        // 获取应用文件路径

                        String filePath = applicationFilePack.getFilePath();

                        log.info("新文件路径:"+filePath);

                        // 获取文件hash

                        String hash = applicationFilePack.getHash();

                        log.info("新文件hash:"+hash);

                        // 获取名称,如agent_1.2.jar

                        String name = applicationFilePack.getName();

                        log.info("新文件名称:" + name);

                        // 调用下载补丁方法

                        String getHash = downLoadFromUrl(filePath, name, path);

                        if (!getHash.equals(hash)) {

                            // 将下载失败的文件删除

                            if (path.contains("/")) {

                                path += "/";

                            }

                            if (path.contains("\\")) {

                                path += "\\";

                            }

                            log.info("将下载失败的文件删除,要删除的文件为:"+path + name);

                            deleteFile(path + name);

                            // hash不同,下次定时任务重新下载

                            log.info("hash不同,下次定时任务重新下载");

                        } else {

                            log.info("新下载的jar文件与原文件hash相同。");

                            // 修改配置文件,将文件版本更新成新版本

                            log.info("修改配置文件更新版本信息:");

                            String[] keyArray = new String[2];

                            keyArray[0] = "version_Number";

                            keyArray[1] = "agent_Name";

                            String[] valueArray = new String[2];

                            valueArray[0] = version;

                            valueArray[1] = name;

                            log.info("新的版本为:" + version);

                            String fileName = "config.ini";

                            ModifyConfig.modifyConfig(keyArray, valueArray, fileName);

                            log.info("修改配置文件更新版本信息,完成。");

                            log.info("将原agent停止:");

                            if (path.contains("/")) {

                                path += "/";

                                log.info("Linux将原agent停止:");

                                String psCommander = "ps -ef|grep "+agentName;

                                log.info("查看进程指令:" + psCommander);

                                Process ps = Runtime.getRuntime().exec(new String[] { "sh", "-c", psCommander });

                                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 ret = sb.toString();

                                // 将获取结果去除回车拆分

                                String[] resultStr = ret.split("\n");

                                for (int j = 0; j < resultStr.length; j++) {

                                    String s = resultStr[j];

                                    // 去除tab键

                                    s = s.replace("    ", " ");

                                    log.info("去除tab键:" + s);

                                    // 将所有的多空格转成单空格

                                    s = s.replaceAll(" +", " ");

                                    log.info("将所有的多空格转成单空格:" + s);

                                    if (s.startsWith(" ")) {

                                        // 将第一个空格截取去除

                                        s = s.substring(1, s.length());

                                        log.info("将第一个空格截取去除:" + s);

                                    }

                                    // 将数据以空格拆分:root 16608 4888 0 15:08 pts/1

                                    // 00:00:47 java -jar agent.jar

                                    String[] retStr = s.split(" ");

                                    log.info("将数据以空格拆分:" + s);

                                    // 获取进程结果的最后一个数据(所下达的指令为何)

                                    String cmdCommander = "";

                                    for (int i = 7; i < retStr.length; i++) {

                                        cmdCommander = cmdCommander + retStr[i];

                                    }

                                    log.info("logCode进程结果的最后一个数据:" + cmdCommander);

                                    log.info("pid为:" + retStr[1]);

                                    if (cmdCommander.contains("java-jar")) {

                                        // 包含文件名,说明这个进程为要杀死的agent进程。获取进程的pid(第二个数据)。

                                        String pid = retStr[1];

                                        log.info("pid为:" + retStr[1]);

                                        // 获取cp进程的标识号,拼接杀进程指令kill -9 进程标识号

                                        String killCommander = "kill -9 " + pid;

                                        // 执行杀进程指令

                                        log.info("---开始执行kill指令:" + killCommander);

                                        Runtime.getRuntime().exec(killCommander);

                                        log.info("---执行kill指令完毕。");

                                    }

                                }

                                // 文件路径

                                String shfileName = path+"/restarJar.sh";

                                log.info("获取sh文件路径如下 :"+shfileName);

                                // 1.删除文件

                                deleteFile(shfileName);

                                log.info("删除文件完成。");

                                // 2.创建文件

                                createNewFile(shfileName);

                                log.info("创建文件完成。");

                                //changeParam为要追加到.sh文件的信息

                                String changeParam = "nohup java -jar /usr/agenthost/" + name +" > /usr/agenthost/logs/myout.file 2>&1 &";

                                log.info("追加到.sh文件的信息:"+ changeParam);

                                // 3.追加内容  \n代表回车换行

                                StringBuffer strBuffer = new StringBuffer();

                                strBuffer.append("#!/bin/sh\n");

                                strBuffer.append(changeParam);

                                appendMethod(shfileName, strBuffer.toString());

                                log.info("追加完成");

                                log.info("执行sh文件:bash "+path+"/restarJar.sh");

                                Runtime.getRuntime().exec("bash "+path+"/restarJar.sh");

                                log.info("执行sh文件完成");

                            }

                            if (path.contains("\\")) {

                                path += "\\";

                                log.info("Windows将原agent停止:");

                                // 查看Windows系统所有正在运行的java程序

                                String psCommander = "jps -l";

                                log.info("查看进程指令:" + psCommander);

                                Process ps = Runtime.getRuntime().exec(psCommander);

                                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 ret = sb.toString();

                                // 将获取结果去除回车拆分

                                String[] resultStr = ret.split("\n");

                                for (int j = 0; j < resultStr.length; j++) {

                                    String s = resultStr[j];

                                    // 去除tab键

                                    s = s.replace("    ", " ");

                                    log.info("去除tab键:" + s);

                                    // 将所有的多空格转成单空格

                                    s = s.replaceAll(" +", " ");

                                    log.info("将所有的多空格转成单空格:" + s);

                                    if (s.startsWith(" ")) {

                                        // 将第一个空格截取去除

                                        s = s.substring(1, s.length());

                                        log.info("将第一个空格截取去除:" + s);

                                    }

                                    // 将数据以空格拆分:root 16608 4888 0 15:08 pts/1

                                    // 00:00:47 java -jar agent.jar

                                    String[] retStr = s.split(" ");

                                    log.info("将数据以空格拆分:" + s);

                                    // 获取进程结果的最后一个数据(所下达的指令为何)

                                    if(retStr.length>1){

                                        String cmdCommander = retStr[1];

                                        log.info("logCode进程结果的最后一个数据:" + cmdCommander);

                                        if (cmdCommander.contains(agentName)) {

                                            // 包含文件名,说明这个进程为要杀死的agent进程。获取进程的pid(第二个数据)。

                                            String pid = retStr[0];

                                            log.info("pid为:" + retStr[0]);

                                            // 获取cp进程的标识号,拼接杀进程指令kill -9 进程标识号

                                            String killCommander = "TASKKILL /F /PID " + pid;

                                            // 执行杀进程指令

                                            log.info("---开始执行kill指令:" + killCommander);

                                            Runtime.getRuntime().exec(killCommander);

                                            log.info("---执行kill指令完毕。");

                                        }

                                    }

                                }

                                // 重启jar文件路径

                                String shfileName = path+"\\restarJar.bat";

                                log.info("获取重启jar文件路径如下 :"+shfileName);

                                // 删除原文件

                                deleteFile(shfileName);

                                log.info("删除原文件完成。");

                                // 重新创建文件

                                createNewFile(shfileName);

                                log.info("重新创建文件完成。");

                                //changeParam为要追加到.sh文件的信息

                                String changeParam = "start javaw -jar " + name;

                                log.info("追加到.bat文件的信息:"+ changeParam);

                                // 将内容追加到重启bat文件中  \n代表回车换行

                                StringBuffer strBuffer = new StringBuffer();

                                strBuffer.append("@echo off\n");

                                strBuffer.append(changeParam+"\n");

                                strBuffer.append("success& exit\n");

                                appendMethod(shfileName, strBuffer.toString());

                                log.info("追加完成");

                                log.info("执行重启jarbat文件");

                                String cmd = "cmd.exe /c   start  " + shfileName;

                                Runtime.getRuntime().exec(cmd);

                                log.info("执行重启jarbat文件完成");

                            }

                        }

                    }

                }

            } else {

                log.info("获取对象为空,没有要更新的!");

            }

        } catch (Exception e) {

            log.info("agent守护进程抛出异常。");

        }

        log.info(" *****agent守护进程定时任务结束*****");

    }

    public static String getMD5Checksum(String filename) throws Exception {

        log.info("进入获取hash方法:");

        byte[] b = createChecksum(filename);

        String result = "";

        for (int i = 0; i < b.length; i++) {

            result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);// 加0x100是因为有的b[i]的十六进制只有1位

        }

        return result;

    }

    public static byte[] createChecksum(String filename) throws Exception {

        InputStream fis = new FileInputStream(filename);// 20px;">将流类型字符串转换为String类型字符串</span>

        byte[] buffer = new byte[1024];

        MessageDigest complete = MessageDigest.getInstance("MD5"); // 如果想使用SHA-1或SHA-256,则传入SHA-1,SHA-256

        int numRead;

        do {

            numRead = fis.read(buffer); // 从文件读到buffer,最多装满buffer

            if (numRead > 0) {

                complete.update(buffer, 0, numRead); // 用读到的字节进行MD5的计算,第二个参数是偏移量

            }

        } while (numRead != -1);

        fis.close();

        return complete.digest();

    }

    public static void deleteFile(String fileName) {

        File file = new File(fileName);

        // 如果是文件,非目录

        if (file.isFile()) {

            file.delete();

        } else {

            return;

        }

    }

    public static void createNewFile(String fileName) {

        File file = new File(fileName);

        // 如果文件不存在,新建一个文件

        if (file.isFile() && !file.exists()) {

            try {

                // 创建文件

                file.createNewFile();

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

    public static void appendMethod(String fileName, String content) {

        try {

            // 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件

            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fileName, true), "GBK");

            osw.write(content);

            osw.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    public static String downLoadFromUrl(String urlStr, String fileName, String savePath) throws IOException {

        String retHash = "";

        URL url = new URL(urlStr);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        // 设置超时间为3秒

        conn.setConnectTimeout(3 * 1000);

        // 防止屏蔽程序抓取而返回403错误

        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

        // 得到输入流

        InputStream inputStream = conn.getInputStream();

        // 获取自己数组

        byte[] getData = readInputStream(inputStream);

        // 文件保存位置

        File saveDir = new File(savePath);

        if (!saveDir.exists()) {

            saveDir.mkdir();

        }

        File file = new File(saveDir + File.separator + fileName);

        FileOutputStream fos = new FileOutputStream(file);

        fos.write(getData);

        if (fos != null) {

            fos.close();

        }

        if (inputStream != null) {

            inputStream.close();

        }

        log.info("info:" + url + " download success");

        // 下载完毕,对补丁(或agent)进行hash处理

        try {

            if (savePath.contains("/")) {

                savePath += "/";

            }

            if (savePath.contains("\\")) {

                savePath += "\\";

            }

            log.info("hash路径:" + savePath + fileName);

            retHash = getMD5Checksum(savePath + fileName);

        } catch (Exception e) {

            e.printStackTrace();

        }

        log.info("获取的文件hash:" + retHash);

        return retHash;

    }

    public static byte[] readInputStream(InputStream inputStream) throws IOException {

        byte[] buffer = new byte[1024];

        int len = 0;

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        while ((len = inputStream.read(buffer)) != -1) {

            bos.write(buffer, 0, len);

        }

        bos.close();

        return bos.toByteArray();

    }

    public static void main(String[] args) {

        try {

            String hash = getMD5Checksum("H:\\agent_v1.2.jar");

            System.out.println(hash);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

转载于:https://my.oschina.net/u/3037187/blog/874759