Java应用程序中执行Linux指令(无第三方jar包)

在一些Java应用程序中,需要执行一些Linux系统命令,例如服务器资源查看、文件操作等。为了实现这样的需求,本文将介绍如何在Java应用程序中执行Linux指令,并提供一些实用的示例。此外,本文不使用第三方jar包,完全基于Java自带的API库。

执行指令获取服务器资源

执行结果

在这里插入图片描述

如何在Java中执行Linux指令

  • 在Java中,我们可以通过Runtime类和Process类提供的API来调用Linux系统命令,以下是两种实现方式

    • Runtime

      Runtime runtime = Runtime.getRuntime();
      // 执行Linux命令,具体命令在command中指定
      Process process = runtime.exec(command);
      
    • ProcessBuilder

      • 相比于Runtime.exec()ProcessBuilder提供了更多的控制和配置选项,本文采用这种方式。

        ProcessBuilder构造函数需要传入一个字符串列表,每个字符串代表一个命令和其参数;也可以是任意多个String... command,在底层会将String... command转为ArrayList

      • 使用ProcessBuilderAPI可以实现更为灵活的命令执行,并且避免了一些潜在的安全风险

      List<String> commands = Arrays.asList("ls", "-l");
      // 调用start()方法来执行命令
      ProcessBuilder pb = new ProcessBuilder(commands);
      Process process = pb.start();
      
  • 获取结果

    // 通过process.getInputStream()获取Linux命令的执行结果的输入流,构造InputStreamReader对象将其转化为字符流
    // 再通过BufferedReader对其进行缓冲区处理,提高读取效率
    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    
    String line = null;
    // 循环读取每一行命令执行结果
    while ((line = reader.readLine()) != null) {
        // 打印每一行命令执行结果到控制台
        System.out.println(line);
    }
    

工具类封装

  • 为提高代码的复用性、可维护性,将执行linux命令工具类进行封装

    public class Resource {
        /**
         * 获取资源使用情况,
         */
        public static void getResourceUsage() {
            String[] cpu = {"/bin/sh", "-c", "ps aux --sort=-%cpu --no-header | head -1 | awk '{printf \"%.2f%%\\n\", $3}'"};
            String[] mem = {"/bin/sh", "-c", "free -t | tail -1 | awk '{printf \"%.2f%%\\n\", $3/$2*100}'"};
            String[] memMax = {"/bin/sh", "-c", "ps aux --sort=-%cpu --no-header | head -1 | awk '{printf \"%.2f%%\\n\", $4}'"};
            try {
                System.out.println("cpu使用最大值%CPU: " + execCommand(cpu));
                System.out.println("内存使用总量%MEM: " + execCommand(mem));
                System.out.println("cpu使用最大进程内存使用值%MEM: " + execCommand(memMax));
            } catch (
                    Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 执行Linux命令工具方法
         *
         * @param commands 命令数组,格式为 {"/bin/sh", "-c", "command xxx"}
         * @return 命令执行完之后返回值
         * @throws IOException
         * @throws InterruptedException
         */
        public static String execCommand(String[] commands) throws IOException, InterruptedException {
            Process process = null;
            BufferedReader reader = null;
            StringBuilder sb = new StringBuilder();
            try {
                process = new ProcessBuilder(commands).start();
                // 获取标准输入流 process.getInputStream()
                reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                // 等待进程结束
                int exitCode = process.waitFor();
                if (exitCode != 0) {
                    throw new RuntimeException("Command exited with non-zero status code: " + exitCode);
                }
            } catch (IOException e) {
                throw new RuntimeException("Failed to execute command: " + e.getMessage());
            } finally {
                if (reader != null) {
                    reader.close();
                }
                if (process != null) {
                    process.destroy();
                }
            }
            return sb.toString();
        }
    }
    

测试

  • 为方便测试,使用springboot提供的@Scheduled(cron = "0/10 * * * * ?")每隔10s执行一次,将资源使用情况打印到日志

    @Component
    @Slf4j
    public class TestTask {
    
        // 每隔10s执行一次
        @Scheduled(cron = "0/10 * * * * ?")
        public void test() {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            log.info("当前执行时间:{}", sdf.format(System.currentTimeMillis()));
            Resource.getResourceUsage();
            log.info("服务器资源检测执行完毕");
        }
    }
    

参考资料

How to Run a Shell Command in Java | Baeldung

ProcessBuilder (Java Platform SE 8 )

Logo

更多推荐