| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- package cn.exlive.monitor.utils;
- import cn.exlive.monitor.config.ProgramsConfig;
- import org.apache.commons.exec.CommandLine;
- import org.apache.commons.exec.DefaultExecuteResultHandler;
- import org.apache.commons.exec.DefaultExecutor;
- import org.apache.commons.exec.ExecuteResultHandler;
- import org.apache.commons.exec.ExecuteWatchdog;
- import org.apache.commons.exec.ProcessDestroyer;
- import org.apache.commons.exec.PumpStreamHandler;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.commons.lang3.SystemUtils;
- import org.apache.commons.lang3.exception.ExceptionUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.boot.system.ApplicationHome;
- import java.io.BufferedInputStream;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.Reader;
- import java.time.Duration;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Objects;
- import java.util.Optional;
- import java.util.concurrent.CompletableFuture;
- import java.util.concurrent.TimeUnit;
- /**
- * 便捷得 Shell 执行工具类
- *
- * <pre>
- *
- * Created by zhaopx.
- * Date: 2025/6/9
- * Time: 12:00
- * Vendor: exlive.cn
- *
- * </pre>
- *
- * @author zhaopx
- */
- public class ShellUtils {
- private static final Logger logger = LoggerFactory.getLogger(ShellUtils.class);
- public static String INSTALL_PATH = getInstallPath();
- public final static String OS = SystemUtils.IS_OS_LINUX ? "linux" : "windows";
- private static ProcessBuilder processBuilder = new ProcessBuilder();
- /**
- * 返回 App HOME
- * @return
- */
- private static String getInstallPath() {
- String appHome = System.getenv("APP_HOME");
- if(StringUtils.isBlank(appHome)) {
- appHome = System.getProperty("app.home");
- }
- if(StringUtils.isBlank(appHome)) {
- // appHome = "D:/Work/Deploy";
- ApplicationHome ah = new ApplicationHome(ShellUtils.class);
- // 获取jar包所在目录
- File source = ah.getSource();
- File dir = ah.getDir();
- if(source == null && dir == null) {
- throw new IllegalStateException("请设置 Monitor APP_HOME 环境变量。");
- }
- if(source == null && dir != null) {
- appHome = dir.getParentFile().getAbsolutePath();
- } else {
- File appHomeFile = Optional.ofNullable(source.getParentFile()).map(File::getParentFile).orElseGet(()->{
- String userDir = System.getProperty("user.dir");
- return new File(org.springframework.util.StringUtils.hasLength(userDir) ? userDir : ".");
- });
- appHome = appHomeFile.getAbsolutePath();
- }
- logger.warn("use app home: {} recommen user set APP_HOME envirment.", appHome);
- }
- // monitor app home 的上一层是 INSTALL_DIR
- File homeDir = new File(appHome);
- String installPath = homeDir.getParentFile().getAbsolutePath();
- logger.info("INSTALL_PATH: {}", installPath);
- File dataDir = new File(homeDir, "data");
- if(!dataDir.exists()) {
- dataDir.mkdir();
- logger.info("mkdir monitor data dir: {}", dataDir.getAbsolutePath());
- }
- return installPath;
- }
- /**
- * @param pathOrCommand 脚本路径或者命令
- * @return
- */
- public static ExecResult exceShell(String pathOrCommand) {
- ExecResult result = new ExecResult();
- StringBuffer stringBuffer = new StringBuffer();
- try {
- // 执行脚本
- Process ps = Runtime.getRuntime().exec(new String[]{"sh", "-c", pathOrCommand});
- // 只能接收脚本echo打印的数据,并且是echo打印的最后一次数据
- BufferedInputStream in = new BufferedInputStream(ps.getInputStream());
- BufferedReader br = new BufferedReader(new InputStreamReader(in));
- String line;
- while ((line = br.readLine()) != null) {
- stringBuffer.append(line);
- stringBuffer.append(System.lineSeparator());
- }
- in.close();
- br.close();
- String execOut = stringBuffer.toString();
- int exitValue = ps.waitFor();
- result.setReturnCode(exitValue);
- if (0 == exitValue) {
- logger.info("{} command exec out is : {} {}", pathOrCommand, System.lineSeparator(), execOut);
- result.setExecResult(true);
- result.setExecOut(execOut);
- } else {
- result.setExecOut("call shell failed. error code is :" + exitValue);
- logger.error("{} command exec out is : {} {}", pathOrCommand, System.lineSeparator(), execOut);
- }
- } catch (Exception e) {
- result.setExecOut(e.getMessage());
- e.printStackTrace();
- }
- return result;
- }
- // 获取cpu架构 arm或x86
- public static String getCpuArchitecture() {
- try {
- Process ps = Runtime.getRuntime().exec("arch");
- StringBuffer stringBuffer = new StringBuffer();
- int exitValue = ps.waitFor();
- if (0 == exitValue) {
- // 只能接收脚本echo打印的数据,并且是echo打印的最后一次数据
- BufferedInputStream in = new BufferedInputStream(ps.getInputStream());
- BufferedReader br = new BufferedReader(new InputStreamReader(in));
- String line;
- while ((line = br.readLine()) != null) {
- logger.info("脚本返回的数据如下: " + line);
- stringBuffer.append(line);
- }
- in.close();
- br.close();
- return stringBuffer.toString();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- public static ExecResult execWithStatus(String workPath, List<String> command, long timeout) {
- Process process = null;
- ExecResult result = new ExecResult();
- try {
- processBuilder.directory(new File(workPath));
- processBuilder.environment();
- processBuilder.command(command);
- processBuilder.redirectErrorStream(true);
- process = processBuilder.start();
- printOutput(process);
- boolean execResult = process.waitFor(timeout, TimeUnit.SECONDS);
- result.setReturnCode(process.exitValue());
- if (execResult && process.exitValue() == 0) {
- logger.info("script execute success");
- result.setExecResult(true);
- result.setExecOut("script execute success");
- } else {
- result.setExecOut("script execute failed");
- }
- return result;
- } catch (Exception e) {
- result.setExecErrOut(e.getMessage());
- e.printStackTrace();
- }
- return result;
- }
- public static ExecResult execWithLogs(String workPath, List<String> command, long timeout) {
- Process process = null;
- ExecResult result = new ExecResult();
- try {
- processBuilder.directory(new File(workPath));
- processBuilder.environment();
- processBuilder.command(command);
- processBuilder.redirectErrorStream(true);
- process = processBuilder.start();
- String output = getOutput(process);
- boolean execResult = process.waitFor(timeout, TimeUnit.SECONDS);
- result.setReturnCode(process.exitValue());
- result.setExecOut(output);
- if (execResult && process.exitValue() == 0) {
- logger.info("script execute success");
- result.setExecResult(true);
- } else {
- }
- return result;
- } catch (Exception e) {
- result.setExecErrOut(e.getMessage());
- e.printStackTrace();
- }
- return result;
- }
- public static ExecResult execWithStatus(String workPath, List<String> command, long timeout, Logger logger) {
- Process process = null;
- ExecResult result = new ExecResult();
- try {
- processBuilder.directory(new File(workPath));
- processBuilder.environment();
- processBuilder.command(command);
- processBuilder.redirectErrorStream(true);
- process = processBuilder.start();
- getOutput(process, logger);
- boolean execResult = process.waitFor(timeout, TimeUnit.SECONDS);
- result.setReturnCode(process.exitValue());
- if (execResult && process.exitValue() == 0) {
- logger.info("script execute success");
- result.setExecResult(true);
- result.setExecOut("script execute success");
- } else {
- result.setExecOut("script execute failed");
- }
- return result;
- } catch (Exception e) {
- result.setExecErrOut(e.getMessage());
- e.printStackTrace();
- }
- return result;
- }
- public static void getOutput(Process process, Logger logger) {
- CompletableFuture.runAsync(() -> {
- BufferedReader inReader = null;
- try {
- inReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
- String line;
- StringBuffer stringBuffer = new StringBuffer();
- while ((line = inReader.readLine()) != null) {
- stringBuffer.append(line);
- stringBuffer.append(System.lineSeparator());
- }
- logger.info(stringBuffer.toString());
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- } finally {
- closeQuietly(inReader);
- }
- BufferedReader errorReader = null;
- try {
- errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
- String line;
- StringBuffer stringBuffer = new StringBuffer();
- while ((line = errorReader.readLine()) != null) {
- stringBuffer.append(line);
- stringBuffer.append(System.lineSeparator());
- }
- logger.error(stringBuffer.toString());
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- } finally {
- closeQuietly(errorReader);
- }
- });
- }
- public static String getOutput(Process process) {
- StringBuffer stringBuffer = new StringBuffer();
- BufferedReader inReader = null;
- try {
- inReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
- String line;
- while ((line = inReader.readLine()) != null) {
- stringBuffer.append(line);
- stringBuffer.append(System.lineSeparator());
- }
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- } finally {
- closeQuietly(inReader);
- }
- return stringBuffer.toString();
- }
- public static void printOutput(Process process) {
- CompletableFuture.runAsync(() -> {
- BufferedReader inReader = null;
- try {
- inReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
- String line;
- StringBuffer stringBuffer = new StringBuffer();
- while ((line = inReader.readLine()) != null) {
- stringBuffer.append(line);
- stringBuffer.append(System.lineSeparator());
- }
- logger.trace(stringBuffer.toString());
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- } finally {
- closeQuietly(inReader);
- }
- });
- }
- public static String getError(Process process) {
- String errput = null;
- BufferedReader reader = null;
- try {
- if (process != null) {
- StringBuffer stringBuffer = new StringBuffer();
- reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
- while (reader.read() != -1) {
- stringBuffer.append("\n" + reader.readLine());
- }
- errput = stringBuffer.toString();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- closeQuietly(reader);
- return errput;
- }
- public static ExecResult exec(String commands) {
- return exec(null, CommandLine.parse(commands), new HashMap<>(), -1, null);
- }
- public static ExecResult exec(String commands, int timeoutSecond) {
- return exec(null, CommandLine.parse(commands), new HashMap<>(), timeoutSecond, null);
- }
- public static ExecResult exec(String workPath, String commands) {
- return exec(workPath, CommandLine.parse(commands), new HashMap<>(), -1, null);
- }
- public static ExecResult exec(String workPath, String commands, int timeoutSecond) {
- return exec(workPath, CommandLine.parse( commands), new HashMap<>(), timeoutSecond, null);
- }
- /**
- * 执行命令,并返回回调信息
- * @param workPath
- * @param commands
- * @param timeoutSecond
- * @param executeResultHandler
- * @return
- */
- public static ExecResult exec(String workPath, String commands, int timeoutSecond, BrodcastExecuteResultHandler executeResultHandler) {
- return exec(workPath, CommandLine.parse( commands), new HashMap<>(), timeoutSecond, executeResultHandler);
- }
- public static ExecResult exec(String workPath, String commands, Map<String, String> envs, int timeoutSecond) {
- return exec(workPath, CommandLine.parse( commands), envs, timeoutSecond, null);
- }
- /**
- * 执行命令,并返回回调信息
- * @param workPath
- * @param commands
- * @param timeoutSecond
- * @param executeResultHandler
- * @return
- */
- public static ExecResult exec(String workPath, String commands, Map<String, String> envs, int timeoutSecond, BrodcastExecuteResultHandler executeResultHandler) {
- return exec(workPath, CommandLine.parse( commands), envs, timeoutSecond, executeResultHandler);
- }
- public static ExecResult exec(List<String> commands) {
- return exec(null, CommandLine.parse(StringUtils.join(commands, " ")), new HashMap<>(), -1, null);
- }
- public static ExecResult exec(List<String> commands, int timeoutSecond) {
- return exec(null, CommandLine.parse(StringUtils.join(commands, " ")), new HashMap<>(), timeoutSecond, null);
- }
- public static ExecResult exec(String workPath, List<String> commands) {
- return exec(workPath, CommandLine.parse(StringUtils.join(commands, " ")), new HashMap<>(), -1, null);
- }
- public static ExecResult exec(String workPath, List<String> commands, int timeoutSecond) {
- return exec(workPath, CommandLine.parse(StringUtils.join(commands, " ")), new HashMap<>(), timeoutSecond, null);
- }
- /**
- * 带有回调的执行命令
- * @param workPath
- * @param commands
- * @param timeoutSecond
- * @param executeResultHandler
- * @return
- */
- public static ExecResult exec(String workPath, List<String> commands, int timeoutSecond, BrodcastExecuteResultHandler executeResultHandler) {
- return exec(workPath, CommandLine.parse(StringUtils.join(commands, " ")), new HashMap<>(), timeoutSecond, null);
- }
- public static ExecResult exec(String workPath, CommandLine commandLine, Map<String, String> envs, int timeoutSecond, DefaultExecuteResultHandler handler) {
- DefaultExecutor executor = new DefaultExecutor();
- executor.setExitValue(-1);
- // handler 记录
- handler = (handler == null ? new DefaultExecuteResultHandler() : handler);
- ShellLogOutputStream output = new ShellLogOutputStream();
- ShellLogOutputStream err = new ShellLogOutputStream();
- executor.setStreamHandler(new PumpStreamHandler(output, err));
- PidExecuteWatchdog watchDog = null;
- // 不限时间
- if(timeoutSecond > 0) {
- watchDog = new PidExecuteWatchdog(Duration.ofSeconds(timeoutSecond).toMillis(), handler);
- executor.setWatchdog(watchDog);
- }
- String exeScript = "bash";
- if (SystemUtils.IS_OS_WINDOWS) {
- // windows 系统不需要执行,也没有权限
- exeScript = "";
- } else {
- // Linux, Mac 系统使用 bash 直接执行脚本
- exeScript = "bash";
- }
- // String cmd = StringUtils.join(commands, " ");
- if(StringUtils.isNotBlank(workPath)) {
- logger.info("from path: {} execute cmd: {}", workPath, commandLine);
- executor.setWorkingDirectory(new File(workPath));
- } else {
- logger.info("execute cmd: " + commandLine);
- }
- Map<String, String> environment = new HashMap<>(System.getenv());
- if(envs != null && !envs.isEmpty()) {
- environment.putAll(envs);
- }
- ExecResult result = new ExecResult();
- final long start = System.currentTimeMillis();
- try {
- executor.execute(commandLine, environment, handler);
- try {
- result.setPid(watchDog != null ? watchDog.getProcessPid() : -1);
- } catch (Exception ignore) {}
- if (timeoutSecond > 0) {
- handler.waitFor(Duration.ofSeconds(timeoutSecond));
- } else {
- handler.waitFor();
- }
- int exitCode = handler.getExitValue();
- result.setUseTime(System.currentTimeMillis() - start);
- result.setExecOut(output.toString());
- result.setReturnCode(exitCode);
- result.setExecErrOut(err.toString());
- result.setExecResult(Objects.equals(0, exitCode));
- return result;
- } catch (Exception e) {
- result.setUseTime(System.currentTimeMillis() - start);
- result.setExecResult(false);
- result.setReturnCode(-1);
- result.setExecOut(output.toString());
- result.setExecErrOut(ExceptionUtils.getRootCauseMessage(e));
- logger.error("execute: " + commandLine + " error.", e);
- return result;
- }
- }
- public static void closeQuietly(Reader reader) {
- try {
- if (reader != null) {
- reader.close();
- }
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
- }
- public static void destroy(Process process) {
- if (process != null) {
- process.destroyForcibly();
- }
- }
- public static void addChmod(String path, String chmod) {
- ArrayList<String> command = new ArrayList<>();
- command.add("chmod");
- command.add("-R");
- command.add(chmod);
- command.add(path);
- execWithStatus(INSTALL_PATH, command, 60, logger);
- }
- public static void addChown(String path, String user, String group) {
- ArrayList<String> command = new ArrayList<>();
- command.add("chown");
- command.add("-R");
- command.add(user + ":" + group);
- command.add(path);
- execWithStatus(INSTALL_PATH, command, 60, logger);
- }
- }
|