JavaはRuntimeを使用してあるJavaプログラムで別のJavaプログラムを起動して閉じる

3561 ワード

主に使用した
Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});

shellコマンドを呼び出すツールクラス:
    public static String runShell(String cmd) throws Exception {
        StringBuilder result = new StringBuilder();

        Process process = null;
        BufferedReader bufrIn = null;
        BufferedReader bufrError = null;

        try {
            //     ,          (         )          |     
            process = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});

            //     ,         (     0)
            process.waitFor();

            //         ,      :              (PS:               )
            bufrIn = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
            bufrError = new BufferedReader(new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8));

            //     
            String line;
            while ((line = bufrIn.readLine()) != null) {
                result.append(line).append('
'); } while ((line = bufrError.readLine()) != null) { result.append(line).append('
'); } } finally { closeStream(bufrIn); closeStream(bufrError); // if (process != null) { process.destroy(); } } return result.toString(); }

jarパケットがインタフェースに転送されると、このメソッドを呼び出し、実行中のjarを停止し、新しいjarを起動します.
JAR_NAME検査は自定して、ここで固定して1つのjarパケット名を使って、jpsの時にこのプロセスを探し当てることを便利にします
  /**
  *jar      
  */
 private ResponseVo myjarPkg(MultipartFile file) throws Exception {
        //myjar  
        String myjarDir = "/data/myjar/";
        File fileDir = new File(myjarDir);
        fileDir.mkdirs();

        //              
        if (!JAR_NAME.equals(file.getOriginalFilename())) {
            return new ResponseVo(-1, "      ");
        }
        File myjarPkg = new File(myjarDir + file.getOriginalFilename());
        //         
        if (myjarPkg.exists()) {
            FileUtils.deleteQuietly(myjarPkg);
        }
        file.transferTo(myjarPkg);
        //  myjar                 
        // jre       jdk              jre     
        String javaHome = System.getProperty("java.home").replace("/jre", "") + "/bin";
        final String java = javaHome + "/java";
        final String jps = javaHome + "/jps";
        String cmd = jps + " -l|grep " + JAR_NAME + "|awk '{print$1}'";
        String pid = ShellUtil.runShell(cmd);
        if (StringUtils.isNotBlank(pid)) {
            cmd = "kill -9 " + pid;
            String killmsg = ShellUtil.runShell(cmd);
            logger.info("kill process pid:{} ,result:{}", pid, killmsg);
            //     3s
            Thread.sleep(3000);
        }
        cmd = "nohup " + java + " -jar " + myjarDir + JAR_NAME + " > " + myjarDir + "myjar.log 2>&1 &";
        String msg = ShellUtil.runShell(cmd);
        logger.info("        : " + msg);
        return new ResponseVo();
    }

ポイントはJava起動のプロセスで、java、jpsなどのコマンドを直接実行することができず、環境変数も取得できず、command not foundを報告します
それでシステムを使いましたgetProperty(「java.home」)は、現在のプログラムを実行するJavaパスを取得し、jreディレクトリをjdkディレクトリに置き換え、jdkディレクトリの下binディレクトリのjavaおよびjpsコマンドを使用して、ニーズを満たすことができます.
また、コマンド文字列のスペースが重要で無視できないことに注意してください.