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

相关推荐

  • 关系型数据库中的行,它们是如何定义和使用的?数据库行是什么

    关系型数据库中的行是数据表中最基本的逻辑存储单元,它由多个字段(列)组成,代表实体的一条完整记录,并通过主键确保唯一性,是构建结构化数据关系的核心基石,行的本质与结构解析在关系型数据库(RDBMS)的二维表模型中,行(Row)并非简单的数据堆砌,而是具有严格逻辑定义的实体实例,理解行的结构,是优化查询性能和维护……

    2026年6月9日
    16100
  • 关系型数据库备份方法与步骤详解?关系型数据库怎么备份

    关系型数据库备份的核心在于构建“本地快照+异地容灾+定期归档”的三重防护体系,确保在数据丢失或勒索攻击时能实现RPO(恢复点目标)趋近于零、RTO(恢复时间目标)分钟级的业务连续性保障,在2026年的数字化环境中,数据已成为企业最核心的资产,无论是金融交易记录还是用户行为日志,一旦丢失都将造成不可逆的损失,传统……

    2026年6月1日
    12000
  • 国际业务中台系统流量多少,国际业务中台系统流量

    国际业务中台系统流量管理的核心在于通过AI驱动的动态路由与多语言智能适配,实现跨境交易转化率提升30%以上,同时确保数据合规与低延迟响应,2026年国际业务中台流量架构演进逻辑随着全球数字化贸易进入深水区,传统的“烟囱式”IT架构已无法应对2026年复杂的跨境业务场景,中台系统不再仅仅是技术支撑平台,而是成为连……

    2026年5月15日
    12800
  • ASP如何过滤CSS样式?

    在Web开发中,ASP(Active Server Pages)作为一种经典的动态网页技术,常用于构建服务器端应用程序,在处理用户输入或动态生成内容时,安全性始终是首要考虑的问题,尤其是如何有效过滤CSS(层叠样式表)相关的代码,以防止XSS(跨站脚本攻击)等安全风险,本文将深入探讨ASP中过滤CSS的方法、最……

    2025年11月29日
    20000
  • 钉钉智能办公电话功能如何?实用性如何体现?

    钉钉智能办公电话并非传统语音通话的简单数字化,而是基于阿里云通义大模型构建的“AI+通信”一体化解决方案,其核心价值在于通过实时语音转写、智能会议纪要及自动化CRM录入,将企业沟通效率提升30%以上,并显著降低人工客服与行政成本, 技术底座与核心功能解析钉钉智能办公电话的底层逻辑已超越单纯的VoIP(网络电话……

    2026年6月12日
    11600

发表回复

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

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN

关注微信