首页 > 编程语言 >Java 代码执行本地命令

Java 代码执行本地命令

时间:2024-03-18 17:13:07浏览次数:33  
标签:Java ProcessBuilder exec 命令 command 代码执行 本地 new line

by emanjusaka from https://www.emanjusaka.top/2024/03/java-exec-local-command 彼岸花开可奈何
本文欢迎分享与聚合,全文转载请留下原文地址。

我们可以在命令行中执行各种命令,比如,创建文件、查看文件夹下文件、调用第三方工具等等。

如果想在 java 代码中执行命令应该怎么操作呢?我们有两种方式可以实现:

  • 通过Runtime.getRuntime().exec调用命令
  • 使用ProcessBuilder类来构建和执行命令

Runtime.getRuntime().exec

Runtime.getRuntime().exec()是Java中用于执行操作系统命令的方法。它允许你在Java程序中执行外部命令,并获取命令的输出和错误信息。

下面是使用Runtime.getRuntime().exec()执行一个简单命令的步骤:

  1. 创建一个Runtime对象,通过调用Runtime.getRuntime()方法获取。
  2. 调用exec()方法,传入要执行的命令和参数。
  3. exec()方法返回一个Process对象,表示正在执行的进程。
  4. 使用Process对象的方法来获取输出、错误流和返回值。
    /**
     * 执行本地命令
     * 不支持管道和重定向机制
     *
     * @param command 命令
     */

    public static void executeLocalCommand(String command) {
        try {
            // 执行命令
            Process process = Runtime.getRuntime().exec(command);

            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                 BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {

                String line;
                while ((line = reader.readLine()) != null) {
                    log.info(command + ",命令执行结果:", line);
                }

                while ((line = errorReader.readLine()) != null) {
                    // 输出标准错误(stderr),标记为错误信息
                    if (line.startsWith("[ERROR]")) {
                        log.error(command + ",命令执行错误:", line);
                    } else {
                        log.warn(command + ",[WARNING]" + line);
                    }
                }

                // 等待命令执行完成
                int exitCode = process.waitFor();
                if (exitCode != 0) {
                    throw new ServiceException("执行命令失败!");
                }
            }
        } catch (IOException | InterruptedException e) {
            Thread.currentThread().interrupt(); // 如果是InterruptedException,则重新设置中断状态
            throw new RuntimeException(e);
        }
        log.info(command + ",命令执行成功");
    }

注意:该方法不支持shell的管道符和重定向机制。它只能分步执行命令,每个命令都是独立的进程。

在进程执行完成后,你应该调用Process对象的waitFor()方法来等待进程结束,并获取进程的返回值。这样可以确保进程正常结束,并且你可以根据返回值进行进一步处理。

如果需要使用管道符和重定向机制,可以考虑使用ProcessBuilder类来构建和执行命令。

ProcessBuilder

ProcessBuilder是Java中用于创建和控制操作系统进程的类。它比Runtime.exec()更加强大,因为它可以处理命令行参数、错误流和输入流,并支持管道和重定向。

下面是使用ProcessBuilder执行一个简单命令的步骤:

  1. 创建一个ProcessBuilder对象,并传入要执行的命令和参数。
  2. 调用start()方法启动进程。
  3. 使用Process对象的方法来获取输出、错误流和返回值。

下面是一个调用的示例:

package top.emanjusaka;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        String[] command = {
                "ls",
                "-l"
        };
        // 创建ProcessBuilder对象,并传入要执行的命令和参数
        ProcessBuilder processBuilder = new ProcessBuilder(command);

        // 启动进程
        Process process = null;
        try {
            process = processBuilder.start();
            // 获取输出流
            try (
                    BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));) {
                String line;
                while ((line = outputReader.readLine()) != null) {
                    System.out.println(line);
                }
                while ((line = errorReader.readLine()) != null) {
                    // 输出标准错误(stderr),标记为错误信息
                    if (line.startsWith("[ERROR]")) {
                        System.out.println(command + ",命令执行错误:" + line);
                    } else {
                        System.out.println(command + ",[WARNING]" + line);
                    }
                }
                // 等待进程执行完成,并获取返回值
                int exitCode = process.waitFor();
                System.out.println("Exit code: " + exitCode);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } catch (InterruptedException | IOException e) {
            throw new RuntimeException(e);
        }
    }
}

执行结果:

上述代码将执行ls -l命令,并将输出打印到控制台。你可以根据需要修改命令和参数来执行其他命令或传递不同的参数。

请注意,使用ProcessBuilder时需要注意以下几点:

  • ProcessBuilder可以处理命令行参数,因此你可以通过将参数作为字符串数组传递给ProcessBuilder的构造函数来传递多个参数。
  • 你可以使用redirectErrorStream(true)方法将错误流合并到输出流中,这样你就可以同时读取标准输出和错误输出。
  • 在进程执行完成后,你应该调用Process对象的waitFor()方法来等待进程结束,并获取进程的返回值。这样可以确保进程正常结束,并且你可以根据返回值进行进一步处理。

本文原创,才疏学浅,如有纰漏,欢迎指正。如果本文对您有所帮助,欢迎点赞,并期待您的反馈交流,共同成长。
原文地址: https://www.emanjusaka.top/2024/03/java-exec-local-command
微信公众号:emanjusaka的编程栈

标签:Java,ProcessBuilder,exec,命令,command,代码执行,本地,new,line
From: https://www.cnblogs.com/emanjusaka/p/18080952/page_18

相关文章

  • 解决问题:java、mysql、docker、linux、redis、solr适合初级或者刚入门的大学生
    java、mysql、redis、linux、docker中的问题Java问题解决,idea问题解决调试,服务器问题解决,项目部署,项目调试linux服务器上的安装以及运行环境的部署docker的部署可做技术栈:java开发:javaweb,jsp,servlet,javase,spring,springboot,ssm服务器:linux问题docker问题,To......
  • Java创建线程的方式到底有哪些?
    一、线程的创建十种方式一个经典的面试八股问题是:java中有几种线程的创建方式?一般的回答是:实现Thread类。实现Runable接口。 实现Callable接口。也可以加上一个利用ExecutorService线程池: 实现Thread类。实现Runable接口。 实现Callable接口。使用ExecutorService线程......
  • java数据结构与算法刷题-----LeetCode45. 跳跃游戏 II
    java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846文章目录解题思路:时间复杂度O(n......
  • java数据结构与算法刷题-----LeetCode55. 跳跃游戏
    java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846文章目录解题思路:时间复杂度O(n......
  • java实现标签排序置顶
    设计思路置顶:将该数据放到全局数据收尾,其余数据顺序不变【将需要置顶数据的sort设置为全局Min(sort)-1】置尾:将数据放到全局末尾,其余不变【将需要置尾的数据sort设置为全局Max(sort)+1】交换:两位位置交换,其余不变【将需要交换数据的sort互换即可】拖动:局部顺序变化【将4插到1......
  • 【Java入门教程】第五讲:if-else控制语句
    现实世界是复杂多变的,同一个程序我们需要根据不同的场景做出不同的反应。在Java编程中,if-else 语句就是这样一种工具,它允许程序根据不同的条件执行不同的代码块。一、基础语法if-else 语句的基本语法结构如下:if(condition){//代码块1:当条件为true时执行}else......
  • Python3 使用 sqlcipher 来增强本地数据的安全性
    使用sqlcipher来增强本地数据的安全性本文是基于系列文章PyQt5+SQLAlchemy做登录注册页的补充,并不单独放在系列文中,主要讲的是,使用sqlcipher来保存本地密码,这比直接使用SQLite更安全关于sqlcipher,官方介绍原文如下:SQLCipherisastandaloneforkoftheSQLitedata......
  • Java初学第三天
    1、封装和多态封装封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作系统的源代码进行有机结合,形成类,其中数据和函数都是类的成员封装、继承、多态是面向对象的主要......
  • Java编程思想读书笔记
    1.finalize()方法垃圾回收器只能回收通过new创建的对象的内存空间,但由于Java可以调用本地方法,本地方法中有可能通过c语言的malloc()方法来分配内存,所以垃圾回收器会执行一次finalize()方法来调用C语言的free()方法(finalize()方法需要自己去编写代码去调用本地方法)来释放内存2.封......
  • Java导出多个Excel放在压缩包里
    之前做过一个导出多个Excel放在压缩包里的需求,当时也是网上找的思路,现在已经找不到之前的文章了,不多废话直接上代码。publicvoidexport(HttpServletRequestrequest,HttpServletResponseresponse){StringzipFileName="zipname.zip";List<Workbook>workbooks......