java执行shell脚本

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));
        }
    }
}

Java执行Shell脚本可以使用`Runtime`类或`ProcessBuilder`类。下面是使用`Runtime`类执行Shell脚本的示例代码: ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class ShellScriptExecutor { public static void main(String[] args) { try { // 执行Shell脚本命令 String command = "sh /path/to/script.sh"; Process process = Runtime.getRuntime().exec(command); // 获取Shell脚本输出结果 BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } // 等待Shell脚本执行完成 int exitCode = process.waitFor(); System.out.println("Shell脚本执行完成,退出码:" + exitCode); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } ``` 上述代码中,`/path/to/script.sh`是你要执行Shell脚本的路径。你可以将实际的Shell脚本路径替换到代码中。 使用`ProcessBuilder`类执行Shell脚本的示例代码如下: ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class ShellScriptExecutor { public static void main(String[] args) { try { // 执行Shell脚本命令 ProcessBuilder processBuilder = new ProcessBuilder("sh", "/path/to/script.sh"); Process process = processBuilder.start(); // 获取Shell脚本输出结果 BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } // 等待Shell脚本执行完成 int exitCode = process.waitFor(); System.out.println("Shell脚本执行完成,退出码:" + exitCode); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } ``` 同样,你需要将实际的Shell脚本路径替换到代码中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值