天天看點

更新檔更新

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