فهرست منبع

1.console数据库连接检查,确认健康状态
2.spare2对console进程及健康端口检查

jyyw 1 سال پیش
والد
کامیت
22b1807171

+ 1 - 0
ipfcst-common/ipfcst-common-security/src/main/java/com/jiayue/ipfcst/common/security/config/WebSecurityConfig.java

@@ -92,6 +92,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements A
 //                .antMatchers("/**").permitAll()
                 .antMatchers("/jarCalculate/**").permitAll()
                 .antMatchers("/calculateView/**").permitAll()
+            .antMatchers("/consoleCheckUp/**").permitAll()
                 .antMatchers("/reportVersion/**").permitAll().anyRequest().authenticated()
 
             .and()

+ 13 - 0
ipfcst-console/src/main/frontend/views/dashboard/index.vue

@@ -14,6 +14,8 @@
                 upload程序:
           <el-button size="mini" type="primary" round style="width: 60px;margin-left: 10px" :loading="btnLonding" @click="check5">状态</el-button>
           <el-button size="mini" type="primary" round style="width: 60px;margin-left: 10px" :loading="btnLonding" @click="check6">重启</el-button>
+          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DB状态:
+          <el-button size="mini" type="primary" round style="width: 60px;margin-left: 10px" :loading="btnLonding" @click="check7">状态</el-button>
         </h3>
         </el-breadcrumb-item>
       </el-breadcrumb>
@@ -1138,6 +1140,17 @@ export default {
             }
           })
         },
+                check7() {
+                  this.visible2 = true
+                  this.lsofData = ['Druid状态', '------------------']
+                  this.$axios.get('/consoleCheckUp/dshealth').then(res => {
+                    if (res.data != null) {
+                      for (let j = 0; j < res.data.length; j++) {
+                        this.lsofData.push(res.data[j])
+                      }
+                    }
+                  })
+                },
     lsof1(i){
       if (this.tableData.length>i){
         if(this.tableData[i].selfPort!=undefined&&this.tableData[i].selfPort!=null){

+ 54 - 0
ipfcst-console/src/main/java/com/jiayue/ipfcst/console/controller/ConsoleCheckUpController.java

@@ -0,0 +1,54 @@
+package com.jiayue.ipfcst.console.controller;
+
+import com.alibaba.druid.stat.DruidDataSourceStatManager;
+import com.alibaba.druid.stat.DruidStatManagerFacade;
+import com.jiayue.ipfcst.common.core.web.vo.ResponseVO;
+import com.jiayue.ipfcst.console.service.ConsoleCheckUpService;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.management.openmbean.TabularData;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping(value = "/consoleCheckUp")
+@Slf4j
+public class ConsoleCheckUpController {
+
+  @Autowired
+  ConsoleCheckUpService consoleCheckUpService;
+
+  @SneakyThrows
+  @GetMapping(value = "/dshealth")
+  public ResponseVO getDBConnStatus() {
+    //    DruidStatManagerFacade dsmf = DruidStatManagerFacade.getInstance();
+    //    List<Map<String, Object>> stats = dsmf.getDataSourceStatDataList();
+    //    stats.forEach(stat -> {
+    //      for (String s : stat.keySet()) {
+    //        log.info("druid stat  {} : {}", s, stat.get(s));
+    //      }
+    //    });
+    //    List<List<String>> traces = dsmf.getActiveConnStackTraceList();
+    //    traces.forEach(trace -> trace.forEach(t -> {
+    //      log.info("druid trace  : {}", t);
+    //    }));
+    //    DruidDataSourceStatManager ddssm = DruidDataSourceStatManager.getInstance();
+    //    TabularData td = ddssm.getDataSourceList();
+    //    td.keySet().forEach(k -> {
+    //      log.info("druid ds  key : {}", k);
+    //    });
+    //    td.values().forEach(v -> {
+    //      log.info("druid ds  key : {}", v);
+    //    });
+    //    log.info("druid ds  type : {}", td.getTabularType().toString());
+    //
+    boolean flag = consoleCheckUpService.checkUp();
+    return flag ? ResponseVO.success() : ResponseVO.fail();
+  }
+
+}

+ 54 - 0
ipfcst-console/src/main/java/com/jiayue/ipfcst/console/service/ConsoleCheckUpService.java

@@ -0,0 +1,54 @@
+package com.jiayue.ipfcst.console.service;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.db.sql.SqlUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+@Service
+@Slf4j
+public class ConsoleCheckUpService {
+
+  @Value("${spring.datasource.druid.username}")
+  private String username;
+
+  @Value("${spring.datasource.druid.password}")
+  private String password;
+
+  @Value("${spring.datasource.druid.driver-class-name}")
+  private String driverClassName;
+
+  @Value("${spring.datasource.druid.url}")
+  private String url;
+
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
+  public Boolean checkUp() throws SQLException {
+    boolean result = false;
+    Connection connection = null;
+    try {
+      String driverClassName = this.driverClassName;
+      String url = this.url;
+      String username = this.username;
+      String password = this.password;
+      Class.forName(driverClassName);
+      connection = DriverManager.getConnection(url, username, password);
+      Statement statement = connection.createStatement();
+      String sql = SqlUtil.formatSql("SELECT 1 FROM DUAL");
+      result = statement.execute(sql);
+    } catch (Exception ex) {
+      log.error(ex.getLocalizedMessage());
+    } finally {
+      IoUtil.close(connection);
+    }
+    return result;
+  }
+
+}

+ 11 - 11
ipfcst-spare2/pom.xml

@@ -208,18 +208,18 @@
             <version>1.5</version>
         </dependency>
 
-        <dependency>
-            <groupId>com.syjy</groupId>
-            <artifactId>calculation-spring-boot-starter</artifactId>
-            <version>0.0.29</version>
+<!--        <dependency>-->
+<!--            <groupId>com.syjy</groupId>-->
+<!--            <artifactId>calculation-spring-boot-starter</artifactId>-->
+<!--            <version>0.0.29</version>-->
 
-            <exclusions>
-                <exclusion>
-                    <groupId>com.alibaba.cloud</groupId>
-                    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
+<!--            <exclusions>-->
+<!--                <exclusion>-->
+<!--                    <groupId>com.alibaba.cloud</groupId>-->
+<!--                    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>-->
+<!--                </exclusion>-->
+<!--            </exclusions>-->
+<!--        </dependency>-->
     </dependencies>
 
     <profiles>    <!--考虑到window 和linux环境 npm命令格式的问题,使用maven的profile实现动态指定命令-->

+ 5 - 12
ipfcst-spare2/src/main/java/com/jiayue/ipfcst/spare2/Spare2Application.java

@@ -5,14 +5,13 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.velocity.app.Velocity;
 import org.apache.velocity.app.VelocityEngine;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.builder.SpringApplicationBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.env.Environment;
 import org.springframework.scheduling.annotation.EnableScheduling;
-import javax.sql.DataSource;
+
 import java.util.Properties;
 import java.util.TimeZone;
 
@@ -24,15 +23,12 @@ import java.util.TimeZone;
  * @since 2019/7/22 9:05
  */
 @Configuration
-@SpringBootApplication()
+@SpringBootApplication
 @Slf4j
 @EnableScheduling
 public class Spare2Application {
 
     private final Environment environment;
-    @Qualifier("dataSource")
-    @Autowired
-    private DataSource dataSource;
 
     @Autowired
     public Spare2Application(Environment environment) {
@@ -40,9 +36,8 @@ public class Spare2Application {
     }
 
     public static void main(String[] args) {
-      TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
-      log.info("GMT+8");
-      ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
+        TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
+        ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
         //变更配置文件读取位置启动
         new SpringApplicationBuilder(Spare2Application.class).run(args);
     }
@@ -56,12 +51,10 @@ public class Spare2Application {
     public VelocityEngine velocityEngine() {
         VelocityEngine ve = new VelocityEngine();
         Properties properties = new Properties();
-        //    String vmsPath = BaseService.class.getClassLoader().getResource("vms").getPath();
         //设置velocity资源加载方式为file
         properties.setProperty("resource.loader", "file");
         //设置velocity资源加载方式为file时的处理类
-        properties
-                .setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
+        properties.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
         properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "");
         properties.setProperty(Velocity.ENCODING_DEFAULT, "UTF-8");
         properties.setProperty(Velocity.INPUT_ENCODING, "UTF-8");

+ 81 - 0
ipfcst-spare2/src/main/java/com/jiayue/ipfcst/spare2/job/ConsoleCheckUpJob.java

@@ -0,0 +1,81 @@
+package com.jiayue.ipfcst.spare2.job;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.jiayue.ipfcst.common.data.dto.ProcessResult;
+import com.jiayue.ipfcst.common.data.util.ShellUtil;
+import com.jiayue.ipfcst.spare2.util.FileUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Service
+@EnableScheduling
+public class ConsoleCheckUpJob {
+
+    @Scheduled(cron = "0/30 * * * * *")
+    public void MonitConsoleUp() {
+        ProcessResult processResult = getPid();
+        boolean error = false;
+        //确认console进程状态
+        if (null == processResult.output || processResult.output.isEmpty()) {
+            log.error("console程序进程未找到,将使用spare2生成文件");
+            error = true;
+        }
+        log.info("console程序进程查询结果:{}",CollectionUtil.join(processResult.output, " "));
+        //console进程存在,访问console健康接口,确认程序状态
+        if (!error) {
+            // 向console发送健康接口请求
+            HttpRequest request = HttpRequest.get("https://localhost:9001/consoleCheckUp/dshealth");
+            HttpResponse response = null;
+            try {
+                log.info("console程序健康状态:发送请求");
+                response = request.timeout(5000).execute();
+                String body = response.body();
+                // code == 0 健康,code == 1 异常
+                log.info("console程序健康状态:{}", body);
+                if (JSONUtil.isJson(body)) {
+                    JSONObject jsonObject = JSONUtil.parseObj(body);
+                    Object code = jsonObject.get("code");
+                    Integer status = Convert.toInt(code);
+                    error = status != 0;
+                }
+            } catch (Exception ex) {
+                log.error("console程序健康状态:{}", ex.getMessage());
+            } finally {
+                IoUtil.closeIfPosible(response);
+            }
+        }
+        //console进程不存在或者console健康接口返回为异常,启动spare2文件生成逻辑
+        if (error) {
+            log.info("spare2程序生成文件");
+        } else {
+            log.info("console程序生成文件");
+        }
+    }
+
+
+    private ProcessResult getPid() {
+        List<String> cmds = new ArrayList<>();
+        Map<String, String> envs = new HashMap<>();
+        envs.put("LC_ALL", "zh_CN.UTF-8");
+        envs.put("LANG", "zh_CN.UTF-8");
+        cmds.add("sh");
+        cmds.add("-c");
+        cmds.add("pgrep -fl ipfcst-console");
+        return ShellUtil.runProcess(cmds, envs, new File(FileUtil.getBinPath()));
+    }
+}

+ 6 - 5
ipfcst-spare2/src/main/java/com/jiayue/ipfcst/spare2/console/job/UploadAppUpJob.java → ipfcst-spare2/src/main/java/com/jiayue/ipfcst/spare2/job/UploadAppUpJob.java

@@ -1,9 +1,9 @@
-package com.jiayue.ipfcst.spare2.console.job;
+package com.jiayue.ipfcst.spare2.job;
 
 import cn.hutool.core.collection.CollectionUtil;
 import com.jiayue.ipfcst.common.data.dto.ProcessResult;
+import com.jiayue.ipfcst.common.data.util.ShellUtil;
 import com.jiayue.ipfcst.spare2.util.FileUtil;
-import com.jiayue.ipfcst.spare2.util.ShellUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -20,16 +20,17 @@ import java.util.Map;
 @EnableScheduling
 public class UploadAppUpJob {
 
-    @Scheduled(cron = "0 0/1 * * * *")
+    @Scheduled(cron = "15 0/1 * * * *")
     public void MonitUploadAppUp() {
         ProcessResult processResult = getPid();
         boolean error = false;
         if (null == processResult.output || processResult.output.isEmpty()) {
-            log.error("未找到上报程序进程,将执行程序启动!");
+            log.error("upload程序进程未找到,将执行程序启动");
             error = true;
         }
         if (error) {
-            processResult = runApp();
+            //processResult = runApp();
+            log.info("upload程序启动");
         }
         log.info(CollectionUtil.join(processResult.output, " "));
     }

+ 242 - 0
ipfcst-spare2/src/main/java/com/jiayue/ipfcst/spare2/util/FileUtil.java

@@ -0,0 +1,242 @@
+package com.jiayue.ipfcst.spare2.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.springframework.util.ResourceUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.security.MessageDigest;
+import java.util.Date;
+
+/**
+ * 文件工具类
+ *
+ * @author xsl
+ * @version 3.0
+ */
+@Slf4j
+public class FileUtil {
+
+    public final static String FILEPATH = FileUtil.getFileUploadPath() + File.separator + "new";
+    public final static String BAKPATH = FileUtil.getFileUploadPath() + File.separator + "bak";
+    public final static String ERRPATH = FileUtil.getFileUploadPath() + File.separator + "err";
+
+    /**
+     * 移动本地文件
+     *
+     * @param remoteAbsoluteFile 远程文件名(包括完整路径)
+     * @param localAbsoluteFile  本地文件名(包括完整路径)
+     * @return 成功时,返回true,失败返回false
+     * @throws Exception
+     */
+    public static void move(String localAbsoluteFile, String remoteAbsoluteFile) throws Exception {
+        move(localAbsoluteFile, remoteAbsoluteFile, true);
+    }
+
+    public static void move(String localAbsoluteFile, String remoteAbsoluteFile, boolean overwrite) throws Exception {
+        File srcFile = new File(localAbsoluteFile);
+        File destDir = new File(remoteAbsoluteFile);
+        StringBuilder opts = new StringBuilder();
+        try {
+            if (!destDir.exists()) {// 如果目录不存在则创建目录
+                boolean b = destDir.mkdirs();
+                if (!b) // 如果创建失败则抛出异常
+                    throw new RuntimeException(destDir + " 目录创建失败");
+            }
+            File desFile = new File(remoteAbsoluteFile + File.separator + srcFile.getName());
+            if (overwrite && desFile.exists()) {
+                FileUtils.deleteQuietly(desFile);
+                opts.append(" >> 覆盖 >> ");
+            } else {
+                opts.append(" >> 移动 >> ");
+            }
+            FileUtils.moveFile(srcFile, desFile);
+            log.info("文件:" + srcFile.getName() + opts + destDir.getPath());
+        } catch (IOException e) {
+            throw new Exception("文件:" + srcFile.getName() + opts + destDir.getPath() + "失败。", e);
+        }
+    }
+
+    //文件内容md5加密
+    public static String getMD5(byte[] fileByte) {
+        String md5 = new String();
+        try {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            md.update(fileByte);
+            byte b[] = md.digest();
+
+            int i;
+
+            StringBuffer buf = new StringBuffer("");
+            for (int offset = 0; offset < b.length; offset++) {
+                i = b[offset];
+                if (i < 0)
+                    i += 256;
+                if (i < 16)
+                    buf.append("0");
+                buf.append(Integer.toHexString(i));
+            }
+
+            md5 = buf.toString();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return md5;
+    }
+
+    /**
+     * 获取文件创建时间
+     *
+     * @param fullFileName
+     * @return
+     */
+    public static Long getFileCreateTime(String fullFileName) {
+        Path path = Paths.get(fullFileName);
+        BasicFileAttributeView basicview = Files.getFileAttributeView(path, BasicFileAttributeView.class, LinkOption.NOFOLLOW_LINKS);
+        BasicFileAttributes attr;
+        try {
+            attr = basicview.readAttributes();
+            Date createDate = new Date(attr.creationTime().toMillis());
+            return createDate.getTime();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return new Date().getTime();
+    }
+
+    /**
+     * 获取项目根路径
+     *
+     * @return
+     */
+    public static String getResourceBasePath() {
+        // 获取跟目录
+        File path = null;
+        try {
+            path = new File(ResourceUtils.getURL("classpath:").getPath());
+
+        } catch (FileNotFoundException e) {
+            // nothing to do
+        }
+        if (path == null || !path.exists()) {
+            path = new File("");
+        }
+
+        String pathStr = path.getAbsolutePath();
+        try {
+            pathStr = URLDecoder.decode(pathStr, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        // 如果是在eclipse中运行,则和target同级目录,如果是jar部署到服务器,则默认和jar包同级
+//    pathStr = pathStr.replace("\\target\\classes", "");
+
+        return pathStr;
+    }
+
+    /**
+     * 获取上报文件目录相对路径
+     *
+     * @return
+     */
+    public static String getFileUploadPath() {
+        return createUploadAllDir("uploadFile");
+    }
+
+    /**
+     * 获取下载文件目录相对路径
+     *
+     * @return
+     */
+    public static String getDownloadFilePath() {
+        return createUploadAllDir("downloadFile");
+    }
+
+
+    /**
+     * 获取日志目录相对路径
+     *
+     * @return
+     */
+    public static String getLogsPath() {
+        return createUploadAllDir("logs");
+    }
+
+    /**
+     * 获取系统脚本相对路径
+     *
+     * @return
+     */
+    public static String getBinPath() {
+        return createUploadAllDir("bin");
+    }
+
+    /**
+     * json数据存储相对路径
+     *
+     * @return
+     */
+    public static String getJsonPath() {
+        return createUploadAllDir("json");
+    }
+
+    /**
+     * 存储接入数据
+     *
+     * @return
+     */
+    public static String getDataPath() {
+        return createUploadAllDir("data");
+    }
+
+
+    private static String createUploadAllDir(String dir) {
+        String path = "";
+        if (System.getProperties().getProperty("file.separator").equals("\\")) {
+            path = new File(getResourceBasePath()).getParentFile().getParentFile().getParentFile().getAbsolutePath() + File.separator + dir;
+        } else {
+            path = "/home/syjy/ipfcstSingle/" + dir;
+        }
+        try {
+            path = URLDecoder.decode(path, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        File file = new File(path);
+        if (!file.exists()) {
+            boolean b = file.mkdirs();
+            if (!b)
+                log.error("目录创建失败" + path);
+        }
+        return path;
+    }
+
+    /**
+     * 获取环境数导据出文件目录相对路径
+     *
+     * @return
+     */
+    public static String getEnvironmentalDataFile() {
+        return createUploadAllDir("environmentalDataFile");
+    }
+
+    /**
+     * 获取临时文件目录相对路径
+     *
+     * @return
+     */
+    public static String getTempFilePath() {
+        return createUploadAllDir("tempFile");
+    }
+}

+ 0 - 91
ipfcst-spare2/src/main/java/com/jiayue/ipfcst/spare2/util/ShellUtil.java

@@ -1,91 +0,0 @@
-package com.jiayue.ipfcst.spare2.util;
-
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.RuntimeUtil;
-import com.jiayue.ipfcst.common.data.dto.ProcessResult;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-
-import java.io.File;
-import java.nio.charset.StandardCharsets;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-@Slf4j
-public class ShellUtil {
-
-    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
-
-    /**
-     * 执行sh命令
-     *
-     * @param cmds
-     * @return
-     */
-    public static ProcessResult runRuntime(List<String> cmds) {
-        log.info("开始执行");
-        ProcessResult processResult = new ProcessResult();
-        if (null == cmds || cmds.isEmpty()) {
-            processResult.setExitCode(1);
-            log.error("命令行为空!");
-        } else {
-            List<String> result = RuntimeUtil.execForLines(StandardCharsets.UTF_8, ArrayUtil.toArray(cmds, String.class));
-            processResult.setOutput(result);
-            processResult.setExitCode(0);
-            result.forEach(log::info);
-        }
-        log.info("执行结束");
-        return processResult;
-    }
-
-    /**
-     * 执行sh命令,可配置环境变量及工作路径
-     *
-     * @param cmds
-     * @param envs
-     * @param workspace
-     * @return
-     */
-    public static ProcessResult runProcess(List<String> cmds, Map<String, String> envs, File workspace) {
-        log.info("开始执行");
-        Process process = null;
-        ProcessResult result = new ProcessResult();
-        List<String> message;
-        try {
-            ProcessBuilder processBuilder = new ProcessBuilder();
-            processBuilder.command(cmds);
-            //命令工作空间
-            if (null != workspace && workspace.exists() && workspace.isDirectory()) {
-                processBuilder.directory(workspace);
-            }
-            //环境变量
-            if (null != envs) {
-                Map<String, String> enviroment = processBuilder.environment();
-                for (String key : envs.keySet()) {
-                    if (enviroment.containsKey(key)) {
-                        if (!StringUtils.equals(enviroment.get(key), envs.get(key))) {
-                            enviroment.put(key, envs.get(key));
-                        }
-                    } else {
-                        enviroment.put(key, envs.get(key));
-                    }
-                }
-            }
-            log.info(String.join(" ", processBuilder.command()));
-            //执行命令
-            process = processBuilder.start();
-            message = IoUtil.readUtf8Lines(process.getInputStream(), new ArrayList<>());
-            result.setOutput(message);
-            result.setExitCode(0);
-        } catch (Exception ex) {
-            result.setExitCode(1);
-        } finally {
-            RuntimeUtil.destroy(process);
-            log.info("执行结束");
-        }
-        return result;
-    }
-}