当前位置: 首页 > 工具软件 > jail-shell > 使用案例 >

java执行shell脚本

马星阑
2023-12-01
package com.utils;

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Date;

public class CommandUtils {

    private static final Logger LOG = LoggerFactory.getLogger(CommandUtils.class);

    private static Boolean isWinOS() {
        return System.getProperty("os.name").toLowerCase().startsWith("win");
    }

    private static Boolean isMacOS() {
        return System.getProperty("os.name").toLowerCase().startsWith("mac");
    }

    private static Process doExecute(String shell, String outputFile, boolean withDetails, boolean append) throws Exception {
        String command = shell;
        if (StringUtils.isNotEmpty(outputFile)) {
            if (withDetails) {
                String commandLog = String.format("\n%s: %s", DateFormatUtils.format(new Date(), "yyyy-MM-dd'T'HH:mm:ss"), command);
                FileUtils.writeStringToFile(new File(outputFile), commandLog, StandardCharsets.UTF_8, append);
                command += " 1>>" + outputFile + " 2>&1";
            } else {
                if (append) {
                    command += " 1>>" + outputFile + " 2>&1";
                } else {
                    command += " 1>" + outputFile + " 2>&1";
                }
            }
        }

        File shellFile = new File(String.format("%s/%d_%s.sh", "/tmp/shell", System.currentTimeMillis(), RandomUtils.randomStr(4)));
        FileUtils.writeStringToFile(shellFile, command, StandardCharsets.UTF_8, false);
        return Runtime.getRuntime().exec("sh " + shellFile.getAbsolutePath());
    }

    private static String getPid(Process process) throws Exception {
        if (process.getClass().getName().contains("UNIXProcess")) {
            // linux获取进程id
            Field pidField = process.getClass().getDeclaredField("pid");
            pidField.setAccessible(true);
            return String.valueOf(pidField.get(process));
        } else {
            // window获取进程id
            Field handleField = process.getClass().getDeclaredField("handle");
            handleField.setAccessible(true);
            long handle = handleField.getLong(process);
            Kernel32 kernel = Kernel32.INSTANCE;
            WinNT.HANDLE windNTHandle = new WinNT.HANDLE();
            windNTHandle.setPointer(Pointer.createConstant(handle));
            return String.valueOf(kernel.GetProcessId(windNTHandle));
        }
    }

    /**
     * 执行命令行
     *
     * @param shell
     * @param outputFile
     * @return
     * @throws IOException
     */
    public static String execute(String shell, String outputFile, boolean withDetails, boolean append) throws Exception {
        Process process = doExecute(shell, outputFile, withDetails, append);
        String pid = getPid(process);
        if (StringUtils.isNotEmpty(outputFile) && withDetails) {
            FileUtils.writeStringToFile(new File(outputFile), "\npid: " + pid, StandardCharsets.UTF_8, true);
        }
        return pid;
    }


    /**
     * 根据pid判断进程是否存在,如果存在,杀掉进程,并清空文件夹
     *
     * @param pid
     * @return 0表示不存在,1表示存在,因为进程号不可能重复,所以输出肯定非0即1
     */
    public static boolean existPid(String pid) {
        if (StringUtils.isEmpty(pid)) {
            return false;
        }
        try {
            BufferedReader bufferedReader = null;
            try {
                String command = "ps -ef | awk '{print $2}' | grep -w '" + pid + "' | wc -l";
                if (isWinOS()) {
                    command = "ps --no-heading " + pid + " | wc -l";
                }
                Process process = doExecute(command, null, false, false);
                if (process != null) {
                    //bufferedReader用于读取Shell的输出内容
                    bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"), 1024);
                    process.waitFor();
                }
                String line;
                //读取Shell的输出内容,并添加到stringBuffer中
                StringBuilder output = new StringBuilder();
                while (bufferedReader != null && (line = bufferedReader.readLine()) != null) {
                    output.append(line).append("\n");
                }
                if (StringUtils.isNotEmpty(output.toString())) {
                    int outputNum = Integer.valueOf(output.toString().trim());
                    return outputNum == 1;
                }
            } finally {
                if (bufferedReader != null) {
                    try {
                        bufferedReader.close();
                    } catch (Exception e) {
                        // ignore exception
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 杀掉进程
     *
     * @param pid
     * @return true, 命令执行成功
     */
    public static void killByPid(String pid, boolean withSubProcess) throws Exception {
        if (existPid(pid)) {
            String command = "kill -9 " + pid;
            if (withSubProcess) {
                command = String.format("ps --ppid %s | awk '{if($1~/[0-9]+/) print $1}' | xargs kill -9 && kill -9 %s", pid, pid);
            }
            Process process = doExecute(command, null, false, false);
            process.waitFor();
            process.destroy();

            LOG.info(String.format("kill process, pid:%s", pid));
        }
    }
}

 类似资料: