Java调用CMD命令如何实现?

核心方法

使用 Runtime 类(传统方式)

try {
    // 执行命令
    Process process = Runtime.getRuntime().exec("cmd /c dir C:\\");
    // 读取命令输出
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getInputStream(), "GBK")  // Windows中文环境用GBK编码
    );
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
    // 等待命令执行完成(阻塞当前线程)
    int exitCode = process.waitFor();
    System.out.println("Exit Code: " + exitCode);
} catch (Exception e) {
    e.printStackTrace();
}
  • 关键参数说明
    • cmd /c [命令]:执行后关闭CMD窗口(/k表示执行后保留窗口)。
    • process.getInputStream():获取命令的标准输出流。
    • process.waitFor():阻塞当前线程直到命令结束。

使用 ProcessBuilder 类(推荐方式)

try {
    // 构建命令及参数(避免手动拼接字符串)
    ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "ping", "www.baidu.com");
    builder.redirectErrorStream(true);  // 合并标准错误和标准输出
    // 启动进程
    Process process = builder.start();
    // 读取输出
    try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getInputStream(), "GBK"))
    ) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
    }
    // 检查执行结果
    if (process.waitFor() == 0) {
        System.out.println("命令执行成功");
    } else {
        System.out.println("命令执行失败");
    }
} catch (Exception e) {
    e.printStackTrace();
}
  • 优势
    • 支持参数列表化(避免命令注入风险)。
    • 可设置工作目录、环境变量。
    • 灵活的重定向输入/输出/错误流。

关键注意事项

  1. 编码问题

    • Windows CMD默认使用GBK编码,Linux/Mac使用UTF-8,错误编码会导致输出乱码:
      new InputStreamReader(process.getInputStream(), "GBK")
  2. 阻塞与超时控制

    • process.waitFor()会无限期阻塞线程,建议使用带超时的版本:
      boolean finished = process.waitFor(10, TimeUnit.SECONDS);
      if (!finished) {
          process.destroy();  // 强制终止进程
      }
  3. 错误流处理

    • 必须同时读取标准输出流和错误流,否则进程可能因缓冲区满而挂起:
      // 分别启动两个线程读取stdout和stderr
      new Thread(() -> readStream(process.getInputStream())).start();
      new Thread(() -> readStream(process.getErrorStream())).start();
  4. 命令注入风险

    • 错误做法:拼接用户输入的字符串(高危!)
      Runtime.getRuntime().exec("cmd /c " + userInput);  // 可能执行恶意命令
    • 正确做法:使用ProcessBuilder分割参数:
      ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "echo", userInput);
  5. 跨平台兼容性

    • Linux/Mac需替换命令前缀:
      String[] command = System.getProperty("os.name").toLowerCase().contains("win") 
          ? new String[]{"cmd.exe", "/c", "dir"}
          : new String[]{"/bin/sh", "-c", "ls"};

完整示例:执行Python脚本并捕获输出

public class ExecuteCMD {
    public static void main(String[] args) {
        try {
            ProcessBuilder builder = new ProcessBuilder("python", "C:/test.py");
            builder.directory(new File("C:/"));  // 设置工作目录
            Process process = builder.start();
            // 异步读取输出
            StringBuilder output = new StringBuilder();
            Thread readThread = new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))
                ) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        output.append(line).append("\n");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            readThread.start();
            // 等待命令结束
            int exitCode = process.waitFor();
            readThread.join();  // 确保输出读取完成
            System.out.println("输出内容:\n" + output);
            System.out.println("退出码: " + exitCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

安全与最佳实践

  1. 最小权限原则:避免以管理员权限执行命令。
  2. 资源释放:用try-with-resources确保流关闭。
  3. 日志记录:记录执行的命令、参数和退出码,便于审计。
  4. 输入验证:严格校验用户输入,禁止直接拼接命令。

引用说明

  • Oracle官方文档:ProcessBuilder, Runtime.exec()
  • 编码问题参考:The Pitfalls of Runtime.exec()
  • 安全建议:OWASP Command Injection

原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/7121.html

(0)
酷番叔酷番叔
上一篇 2025年7月12日 21:02
下一篇 2025年7月12日 21:41

相关推荐

  • ASP网站文件管理如何高效安全?

    在网站开发与维护过程中,文件管理是确保系统稳定运行和高效操作的核心环节,对于基于ASP(Active Server Pages)技术的网站而言,由于其在动态内容生成、服务器端脚本执行等方面的独特优势,文件管理不仅涉及静态资源的组织,还需兼顾脚本逻辑、数据库交互及安全性等多维度需求,本文将围绕ASP网站文件管理的……

    2025年12月21日
    9100
  • MATLAB的factor函数如何自动分解质因数与多项式?

    函数核心功能质因数分解(输入为整数)将正整数分解为质因数的乘积,结果以行向量形式返回,示例代码:n = 60;factors = factor(n) % 对60进行质因数分解输出:factors = [2, 2, 3, 5] % 即 2×2×3×5=60多项式因式分解(输入为符号表达式)对符号多项式进行因式分解……

    2025年7月15日
    15200
  • asp软件系统的功能特点及适用领域是什么?

    ASP软件系统作为一种基于服务器端脚本技术的Web应用程序开发框架,自诞生以来在企业级应用开发领域占据着重要地位,它通过在服务器端执行代码,动态生成HTML页面,为用户提供交互性强、功能丰富的Web服务,本文将从技术架构、发展历程、应用场景、优势挑战及未来趋势等多个维度,全面剖析ASP软件系统的核心价值与实践意……

    2025年11月19日
    9600
  • ASP电子相册如何快速搭建与优化?

    在数字化时代,人们越来越倾向于将珍贵的回忆以电子形式保存和分享,ASP电子相册作为一种基于ASP(Active Server Pages)技术开发的在线相册管理系统,凭借其简单易用、扩展性强和跨平台兼容等优势,成为许多个人用户和小型团队管理照片的理想选择,本文将详细介绍ASP电子相册的特点、技术实现、功能模块以……

    2025年12月20日
    9200
  • 如何在Vim中使用写命令?

    基础保存操作进入命令模式打开文件后,按 Esc 键确保处于普通模式(屏幕左下角无 –INSERT– 提示),输入写命令输入英文冒号 (屏幕左下角出现 ),紧接着输入:w + Enter → 保存文件(write)wq + Enter → 保存并退出(write + quit)x + Enter → 保存并退……

    2025年7月13日
    16600

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN

关注微信