日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

簡介

最近運維人員提出需求,增加一個運維頁面, 查詢當前的業(yè)務進程信息包括:進程名稱、啟動命令、啟動時間、運行時間等,可以通過頁面點擊重啟按鈕,可以重啟后端的一系列系統(tǒng)進程。

思路

JAVA程序獲取linux進程信息可以通過shell腳本獲取進程信息、通過讀取proc文件系統(tǒng)獲取進程信息。 但是為了系統(tǒng)的安全性、方便維護等角度出發(fā),更多的是java通過shell獲取和linux交互能力。

java程序中要執(zhí)行l(wèi)inux命令主要依賴2個類:Process和Runtime:

Process:

ProcessBuilder.start() 和 Runtime.exec 方法創(chuàng)建一個本機進程,并返回 Process 子類的一個實例, 該實例可用來控制進程并獲得相關(guān)信息。Process 類提供了執(zhí)行從進程輸入、執(zhí)行輸出到進程、等待進程完成、 檢查進程的退出狀態(tài)以及銷毀(殺掉)進程的方法。 創(chuàng)建進程的方法可能無法針對某些本機平臺上的特定進程很好地工作,比如,本機窗口進程,守護進程,Microsoft windows 上的 Win16/DOS 進程,或者 shell 腳本。創(chuàng)建的子進程沒有自己的終端或控制臺。它的所有標準 io(即 stdin、stdout 和 stderr) 操作都將通過三個流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父進程。 父進程使用這些流來提供到子進程的輸入和獲得從子進程的輸出。因為有些本機平臺僅針對標準輸入和輸出流提供有限的緩沖區(qū)大小, 如果讀寫子進程的輸出流或輸入流迅速出現(xiàn)失敗,則可能導致子進程阻塞,甚至產(chǎn)生死鎖。 當沒有 Process 對象的更多引用時,不是刪掉子進程,而是繼續(xù)異步執(zhí)行子進程。 對于帶有 Process 對象的 Java 進程,沒有必要異步或并發(fā)執(zhí)行由 Process 對象表示的進程。

  • 特別需要注意的是:

1,創(chuàng)建的子進程沒有自己的終端控制臺,所有標注操作都會通過三個流

(getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父進程(父進程可通過這些流判斷子進程的執(zhí)行情況)

2,因為有些本機平臺僅針對標準輸入和輸出流提供有限的緩沖區(qū)大小,如果讀寫子進程的輸出流或輸入流迅速出現(xiàn)失敗,

則可能導致子進程阻塞,甚至產(chǎn)生死鎖


特別需要注意:如果子進程中的輸入流,輸出流或錯誤流中的內(nèi)容比較多,最好使用緩存(注意上面的情況2)

Runtime

每個Java應用程序都有一個Runtime類實例,使應用程序能夠與其運行的環(huán)境相連接。可以通過getRuntime方法獲取當前運行時環(huán)境。 應用程序不能創(chuàng)建自己的Runtime類實例。

Process exec(String command) 
          在單獨的進程中執(zhí)行指定的字符串命令。
 Process exec(String command, String[] envp) 
          在指定環(huán)境的單獨進程中執(zhí)行指定的字符串命令。
 Process exec(String command, String[] envp, File dir) 
          在有指定環(huán)境和工作目錄的獨立進程中執(zhí)行指定的字符串命令。
 Process exec(String[] cmdarray) 
          在單獨的進程中執(zhí)行指定命令和變量。 
 Process exec(String[] cmdarray, String[] envp) 
          在指定環(huán)境的獨立進程中執(zhí)行指定命令和變量。 
 Process exec(String[] cmdarray, String[] envp, File dir) 
          在指定環(huán)境和工作目錄的獨立進程中執(zhí)行指定的命令和變量。
command:一條指定的系統(tǒng)命令。

envp:環(huán)境變量字符串數(shù)組,其中每個環(huán)境變量的設(shè)置格式為name=value;如果子進程應該繼承當前進程的環(huán)境,則該參數(shù)為null。

dir:子進程的工作目錄;如果子進程應該繼承當前進程的工作目錄,則該參數(shù)為null。

cmdarray:包含所調(diào)用命令及其參數(shù)的數(shù)組。

獲取進程信息

  • 獲取進程的shell字符串 ps aux | grep procName| grep -v grep
  • java 調(diào)用shell 獲取進程信息
/**
     * 執(zhí)行shell 獲取進程列表信息
     * @param cmd
     * @return
     */
    private List<ProcessBean> queryProcessByShellCmd(final String cmd) {
        List<ProcessBean> processBeanList = new ArrayList<ProcessBean>();
        Process process = null;
        BufferedReader bufferOutReader = null, buffErrReader = null;
        String command = StringUtils.trimToNull(cmd);

        if(StringUtils.isEmpty(command)) {
            return processBeanList;
        }

        try {
            process = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", command});
            process.waitFor();
            bufferOutReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            String line = null;
            while((line = bufferOutReader.readLine()) != null) {
                //解析ps返回的進程信息,組裝成ProcessBean對象
                ProcessBean processBean = parserProcessBean(line);

                if (processBean == null) {
                    continue;
                }

                logger.info("=============>>> 查詢進程返回信息:{},解析進程對象信息:{}", line, processBean);
                processBeanList.add(processBean);
            }

            bufferOutReader.close();
            bufferOutReader = null;
            buffErrReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

            while((line = buffErrReader.readLine()) != null) {
                logger.info("=============>>> 讀取錯誤管道流信息:{}", line);
            }

            buffErrReader.close();
            buffErrReader = null;
            process.destroy();
            process = null;
        } catch (IOException e) {
            logger.error("======>>執(zhí)行Shell腳本失敗, e:{}", e);
        } catch (InterruptedException e) {
            logger.error("======>>執(zhí)行Shell腳本失敗, e:{}", e);
        } finally {
            try {
                if(bufferOutReader != null) {
                    bufferOutReader.close();
                }
                if(buffErrReader != null) {
                    buffErrReader.close();
                }
                if(process != null) process.destroy();
            } catch (Exception e){
                logger.error("===========>> {}", e);
            }
        }

        return processBeanList;
    }

查詢所需的進程列表信息

/**
     * 查詢進程列表
     * @return
     */
    private List<ProcessBean> queryProcessList() {
        List<ProcessBean> processBeanList = new ArrayList<ProcessBean>();

        String osname = SystemUtils.osName().toLowerCase();
        if(osname.indexOf("window") >= 0) {
            return processBeanList;
        }

        final String iafCmd = "ps aux | grep iaf | grep -v grep";
        final String dimpleCmd = "ps aux | grep dimp | grep -v grep";
        final String tradeCmd = "ps aux | grep  | grep -v grep";
        final String TomcatCmd = "ps aux | grep java | grep tomcat | grep -v grep";

        List<ProcessBean> iafProcessList = queryProcessByShellCmd(iafCmd);
        List<ProcessBean> dimpleProcessList = queryProcessByShellCmd(dimpleCmd);
        List<ProcessBean> tradeProcessList = queryProcessByShellCmd(tradeCmd);
        List<ProcessBean> tomcatProcessList = queryProcessByShellCmd(tomcatCmd);
        processBeanList.addAll(iafProcessList);
        processBeanList.addAll(dimpleProcessList);
        processBeanList.addAll(tradeProcessList);
        processBeanList.addAll(tomcatProcessList);
        return processBeanList;
    }
Java通過shell腳本監(jiān)控重啟服務

 

重啟業(yè)務進程

為了解決在某個進程啟動失敗的時候,web端可以獲取到該進程的信息, 需要通過shell返回一個int值, 每個進程啟動結(jié)果占用1個bit位方式實現(xiàn),web端獲取結(jié)果后,解決返回的結(jié)果,然后判斷是否有進程啟動失敗。

首先準備好shell腳本,內(nèi)容如下:

#!/bin/bash
fileHome=/home/lehoon/interface
#返回值,默認0
retParam="0"

if [ -n "$1" ] ;then
    fileHome=$1
fi

interface_home=$fileHome

#查詢gateway的守護shell是否存在,存在就結(jié)束掉
pid=$(ps -fe | grep run_gateway.sh | grep -v grep | awk '{print $2}')
for x in $pid; do kill -9 $x; done

pkill -9 gateway
#sleep 2s
#echo Stop gateway

#Nginx stop
/usr/local/sbin/nginx -s stop
#sleep 2s
#echo Stop nginx

pkill -9 interface_uapmm
#sleep 2s
#echo Stop interface_uapmm...

cd $interface_home/interface_uapmm/bin
sh $interface_home/interface_uapmm/bin/startup.sh > startlup.log&

#sleep 2s
#echo Start interface_uapmm done.

cd $interface_home/gateway/bin
sh $interface_home/gateway/bin/startup.sh > startup.log&
#sleep 2s
#echo Start gateway done.

cd /usr/local/sbin/
sh /usr/local/sbin/run_nginx.sh >> nginx.log &
#sleep 1s

sleep 1s

OLD_IFS="$IFS"
IFS=" "
#query interface_uapmm program is exits
interface_uapmm_pid=$(ps -fe | grep "./interface_uapmm" | grep -v grep | awk '{print $2}')
interface_uapmm_pid_array=($interface_uapmm_pid)
interface_uapmm_pid_len=${#interface_uapmm_pid_array[@]}

if [ $interface_uapmm_pid_len -eq 1 ]; then
    retParam=1
fi

#query gateway program is exits
gateway_shell_pid=$(ps -fe | grep "gateway" | grep -v grep | awk '{print $2}')
gateway_shell_pid_array=($gateway_shell_pid)
gateway_shell_pid_len=${#gateway_shell_pid_array[@]}

if [ $gateway_shell_pid_len -eq 1 ]; then
    retParam=$(($retParam + 2))
fi

#query nginx program is exits
nginx_pid=$(ps -fe | grep "nginx" | grep -v grep | awk '{print $2}')
nginx_pid_array=($nginx_pid)
nginx_pid_len=${#nginx_pid_array[@]}

if [ $nginx_pid_len -eq 1 ]; then
    retParam=$(($retParam + 4))
fi


IFS="$OLD_IFS"
echo $retParam

shell通過返回一個integer值,java獲取到后,通過判斷結(jié)果就可以知道哪些進程啟動失敗了。

java代碼如下:

    /**
     * 重啟接口腳本
     * @return
     */
    @RequestMApping(value = "interface/restart")
    @RequiresPermissions(value = {"business:operation:maintenance:interface:restart"})
    public String  restartInterface(HttpServletRequest request, HttpServletResponse response) throws BusinessException{
        String osname = SystemUtils.osName().toLowerCase();
        if(osname.indexOf("window") >= 0) {
            //增加日志記錄
            LogUtils.saveLog(request, "系統(tǒng)運維", "手動重啟接口系統(tǒng)失敗, 不支持當前window系統(tǒng)",
                    Log.TYPE_ACCESS, UserUtils.getUser().getId());
            throw new BusinessException("-1", "運維腳本不支持Window系統(tǒng),重啟接口失敗.");
        }

        String shellDictName = SHELL_FILE_NAME_MAP.get("interface");
        String shellFile = DictUtils.getDictValue(shellDictName, "SYSTEM_MAINTENANCE", "");
        shellFile = StringUtils.trimToEmpty(shellFile);
        logger.info(String.format("======>>手動重啟接口系統(tǒng),接口啟動shell腳本[%s]", shellFile));

        if(StringUtils.isEmpty(shellFile)) {
            //增加日志記錄
            LogUtils.saveLog(request, "系統(tǒng)運維",
                    "手動重啟接口系統(tǒng)失敗, 接口啟動shell腳本沒有配置在字典表中",
                    Log.TYPE_ACCESS, UserUtils.getUser().getId());
            logger.info("======>>手動重啟接口系統(tǒng)失敗,接口啟動shell腳本沒有配置在字典表中");
            throw new BusinessException("-1", "接口啟動shell腳本沒有配置在字典表中,啟動失敗.");
        }

        String shellResult = StringUtils.trimToEmpty(runShellFile(shellFile));
        logger.info(String.format("======>>執(zhí)行shell腳本[%s],返回值[%s]", shellFile, shellResult));
        int shellResultCode = -1;
        try {
            shellResultCode = Integer.parseInt(shellResult);
        } catch (NumberFormatException e) {
            logger.error("============>>> 轉(zhuǎn)換shell腳本返回結(jié)果失敗{}", e);
            //增加日志記錄
            LogUtils.saveLog(request, "系統(tǒng)運維",
                    String.format("手動重啟接口系統(tǒng)失敗, 轉(zhuǎn)換shell腳本返回結(jié)果失敗,返回結(jié)果%s", shellResult),
                    Log.TYPE_ACCESS, UserUtils.getUser().getId());
            throw new BusinessException("-1", "接口啟動失敗,請檢查shell腳本是否有誤.");
        }

        if(RESTART_INTERFACE_SUCCESS == shellResultCode) {
            //增加日志記錄
            LogUtils.saveLog(request, "系統(tǒng)運維","交易接口重啟成功",
                    Log.TYPE_ACCESS, UserUtils.getUser().getId());
            AjaxSuccess success = new AjaxSuccess("交易接口重啟成功");
            return renderJson(response, success);
        }

        StringBuilder sb = new StringBuilder("重啟接口失敗, 未啟動成功的進程包括:");
        //查詢錯誤進程信息
        //interface_uapmm進程
        if((shellResultCode & 0x1) == 0) {
            //interface_uapmm出錯
            sb.append("結(jié)果共享緩存、");
        }

        if(((shellResultCode >> 1) & 0x1) == 0) {
            //dimphq run_dimp.sh腳本出錯
            sb.append("行情啟動Shell進程、");
        }

        //gateway進程
        if(((shellResultCode >> 2) & 0x1) == 0) {
            //gateway出錯
            sb.append("接口網(wǎng)關(guān)、");
        }

        if(((shellResultCode >> 3) & 0x1) == 0) {
            //nginx腳本出錯
            sb.append("nginx、");
        }


        sb.deleteCharAt(sb.length() - 1);
        String message = sb.toString();
        logger.info("=====>>>>管理員:{},本次重啟接口進程失敗, {}", UserUtils.getUser().getLoginName(), message);
        //增加日志記錄
        LogUtils.saveLog(request, "系統(tǒng)運維", message, Log.TYPE_ACCESS, UserUtils.getUser().getId());
        throw new BusinessException("-1", message);
    }

分享到:
標簽:Java
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定