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

相关推荐

  • Windows系统卡顿死机怎么办?

    Windows系统是由微软开发的图形用户界面操作系统,提供直观的用户体验、多任务处理能力、文件管理功能,支持广泛的应用软件和硬件设备,是个人电脑的主流操作系统。

    2025年7月1日
    1300
  • compress命令如何实现高效压缩?

    compress命令使用LZW算法压缩文件,显著减小体积,生成带“.Z”后缀的压缩包,需配套uncompress解压,作为早期Unix工具,其效率已被gzip等取代,且曾涉及专利问题。

    2025年7月13日
    1100
  • 快速掌握arches命令配置技巧?

    Arches命令是文化遗产管理平台Arches的核心命令行工具,用于项目初始化、环境配置、数据包管理、数据库操作及系统扩展,是部署、维护和定制Arches应用的基础。

    2025年6月18日
    1500
  • 旋转角度如何定义方向本质?

    旋转角度描述物体绕固定点转动的量值大小,其方向则由旋转轴(通过右手法则或正负号)确定,两者共同完整定义了空间中的旋转运动。

    2025年6月18日
    1500
  • 为什么你越努力,离成功却越来越远?

    在C语言中,命令行输入主要通过两种方式实现:命令行参数(程序启动时传递)和运行时交互输入(程序运行中从键盘读取),以下是详细说明:命令行参数(argc 和 argv)当通过终端启动程序时,可直接在命令后附加参数:./myprogram arg1 arg2在C代码中通过 main 函数的参数获取:int main……

    2025年6月26日
    1300

发表回复

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

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN

关注微信