Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何在 Java 中运行 shell 命令-Java快速入门教程

如何在 Java 中运行 shell 命令-Java快速入门教程

作者头像
jack.yang
发布于 2025-04-05 12:02:06
发布于 2025-04-05 12:02:06
14900
代码可运行
举报
运行总次数:0
代码可运行

1. 概述

在本文中,我们将学习如何从 Java 应用程序执行 shell 命令。

首先,我们将使用 .exec() 方法,其由运行时类提供。然后,我们将了解ProcessBuilder,它更易于定制。

2. 操作系统依赖性

命令行管理程序命令依赖于操作系统,因为它们的行为因系统而异。因此,在我们创建任何进程来运行我们的 shell 命令之前,我们需要了解运行 JVM 的操作系统。

此外,在Windows上,shell通常被称为cmd.exe。相反,在Linux和macOS上,shell命令使用/bin/sh运行。为了在这些不同的机器上兼容,我们可以以编程方式来处理:如果在Windows机器上附加cmd.exe,否则附加/bin/sh。例如,我们可以通过从System类中读取 “os.name” 属性来检查运行代码的计算机是否是 Windows 计算机

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
boolean isWindows = System.getProperty("os.name")
  .toLowerCase().startsWith("windows");Copy

3. 输入和输出

通常,我们需要连接进程的输入和输出流。具体来说,输入流充当标准输入,输出充当过程的标准输出。我们必须始终使用输出流。否则,我们的流程将不会返回,并将永远挂起。

让我们实现一个名为StreamGobbler 的常用类,它使用一个InputStream

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static class StreamGobbler implements Runnable {
    private InputStream inputStream;
    private Consumer<String> consumer;

    public StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
        this.inputStream = inputStream;
        this.consumer = consumer;
    }

    @Override
    public void run() {
        new BufferedReader(new InputStreamReader(inputStream)).lines()
          .forEach(consumer);
    }
}Copy

此类实现Runnable接口,这意味着任何执行程序都可以执行它。

4.运行时.exec()

接下来,我们将使用 .exec() 方法生成一个新进程,并使用之前创建的StreamGobler

例如,我们可以列出用户主目录中的所有目录,然后将其打印到控制台:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String homeDirectory = System.getProperty("user.home");
Process process;
if (isWindows) {
    process = Runtime.getRuntime()
      .exec(String.format("cmd.exe /c dir %s", homeDirectory));
} else {
    process = Runtime.getRuntime()
      .exec(String.format("/bin/sh -c ls %s", homeDirectory));
}
StreamGobbler streamGobbler = 
  new StreamGobbler(process.getInputStream(), System.out::println);
Future<?> future = Executors.newSingleThreadExecutor().submit(streamGobbler);

int exitCode = process.waitFor();
assert exitCode == 0;

future.get(); // waits for streamGobbler to finishCopy

在这里,我们使用.newSingleThreadExecutor()创建了一个新的子进程,然后使用.submit()运行包含shell命令的进程。此外,.submit() 返回一个Future对象,我们用它来检查进程的结果。此外,请确保在返回的对象上调用 .get() 方法以等待计算完成。

注意:JDK 18 deprecates.exec(String command)来自运行时类。

4.1. 句柄管道

目前,无法使用 .exec() 处理管道。幸运的是,管道是外壳特征。因此,我们可以在其中创建要使用的管道的整个命令并将其传递给.exec():

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (IS_WINDOWS) {
    process = Runtime.getRuntime()
        .exec(String.format("cmd.exe /c dir %s | findstr \"Desktop\"", homeDirectory));
} else {
    process = Runtime.getRuntime()
        .exec(String.format("/bin/sh -c ls %s | grep \"Desktop\"", homeDirectory));
}Copy

在这里,我们列出用户主页中的所有目录并搜索“桌面”文件夹。

5.流程生成器

或者,我们可以使用ProcessBuilder,它优于运行时方法,因为我们可以自定义它,而不仅仅是运行字符串命令。

简而言之,通过这种方法,我们能够:

  • 使用 更改运行 shell 命令的工作目录。目录()
  • 通过提供键值映射到 .environment() 来更改环境变量
  • 以自定义方式重定向输入和输出流
  • 使用 .inheritIO() 将它们都继承到当前 JVM 进程的流中

同样,我们可以运行与前面示例中相同的 shell 命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ProcessBuilder builder = new ProcessBuilder();
if (isWindows) {
    builder.command("cmd.exe", "/c", "dir");
} else {
    builder.command("sh", "-c", "ls");
}
builder.directory(new File(System.getProperty("user.home")));
Process process = builder.start();
StreamGobbler streamGobbler = 
  new StreamGobbler(process.getInputStream(), System.out::println);
Future<?> future = Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
assert exitCode == 0;
future.get(10, TimeUnit.SECONDS)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
java Runtime.exec()执行shell/cmd命令:常见的几种陷阱与一种完善实现
我们项目要java执行命令“dmidecode -s system-uuid”获取结果,然而碰到问题,当项目一直执行好久后,Runtime.getRuntime().exec()获取结果为空,但也不报错,重启项目就又可以了,所以猜测属于陷阱2,并进行记录。
刘大猫
2024/11/17
8460
java 执行shell命令及日志收集避坑指南
有时候我们需要调用系统命令执行一些东西,可能是为了方便,也可能是没有办法必须要调用。涉及执行系统命令的东西,则就不能做跨平台了,这和java语言的初衷是相背的。
烂猪皮
2021/01/14
2.7K0
【转】Java中Runtime.exec的一些事 
Runtime类是一个与JVM运行时环境有关的Singleton类,有以下几个值得注意的地方:
yiduwangkai
2019/09/17
3.1K0
Java魔法堂:调用外部程序
Java虽然五脏俱全但总有软肋,譬如获取CPU等硬件信息,当然我们可以通过JNI调用C/C++来获取,但对于对C/C++和Windows API不熟的码农是一系列复杂的学习和踩坑过程。那能不能通过简单一些、学习成本低一些的方式呢?答案是肯定的,在功能实现放在首位的情况下,借他山之石是最简洁有力的做法。
^_^肥仔John
2021/02/25
1.7K0
Java魔法堂:调用外部程序
Java 配 Shell 等于美酒加咖啡
技术上又何尝不是如此呢?先假设一个场景:BOSS 让你实现一个服务监控的指挥室,能看到每个服务器的磁盘剩余空间,能看到。。。能看到。。。
一猿小讲
2019/09/17
8590
Java 配 Shell 等于美酒加咖啡
Java调用CMD命令
Windows下复制: copy C:\server\data\ccgavr\1.png C:\server\data\ccgavr\2.png Windows重命名: ren 1.png 3.png ren C:\server\data\ccgavr\1.png C:\server\data\ccgavr\3.png(DOS中提示命令语法不正确,powershell则可以)
JaneYork
2023/10/11
4050
Java调用CMD命令
Linux:java通过Runtime.getRuntime().exec()执行shell,Process.waitFor()返回Required key not available(126)问题
因为看到错误码对应的原因是:Required key not available,所需的Key不可用。查找了很多相关解决办法,发现都不太相关。
鲲志说
2025/04/07
830
Linux:java通过Runtime.getRuntime().exec()执行shell,Process.waitFor()返回Required key not available(126)问题
Process类详解
ProcessBuilder是一个final类,Process是一个抽象类。ProcessBuilder.start() 和 Runtime.exec() 方法都被用来创建一个操作系统进程(执行命令行操作),并返回 Process 子类的一个实例,该实例可用来控制进程状态并获得相关信息。
matt
2022/10/25
1.7K0
聊聊PowerJob的AbstractScriptProcessor
tech/powerjob/official/processors/impl/script/AbstractScriptProcessor.java
code4it
2024/01/04
1100
ProcessBuilder API 指南-Java快速进阶教程
Process API提供了一种在 Java 中执行操作系统命令的强大方法。但是,它有几个选项,可能会使其使用起来很麻烦。
jack.yang
2025/04/05
1090
红队笔记专属-shell备忘录
建议直接复制粘贴到笔记,或点赞收藏,因为时常会用到,这是整理的一些常见的反向shell和特权提升的笔记文档,红队成员必会!
Gamma实验室
2022/04/26
1.1K0
Java程序员的日常 —— 多进程开发
最近再弄进程管理相关的工作,因此必要的就涉及到各种系统下关于进程的管理。 这里简单的介绍下: 如何在Java中执行命令 在windows下肯定是dos命令了,而在linux则为shell命令。执行的方式差不多相同: 方法1:Runtime windows版本: Process process = Runtime.getRuntime().exec("ipconfig /all"); Linux版本: Process process = Runtime.getRuntime().exec("ifcon
用户1154259
2018/01/17
1.2K0
Java程序员的日常 —— 多进程开发IO阻塞问题
本篇仍旧是源于最近的工作,总结一下纪念那些年埋下的坑... 背景故事 需求:“使用进程方式启动另一个程序!” 开发:“OK! Runtime.getRuntime().exec("xxxx")” 需求:“启动以后能看到输出消息不!” 开发:“OK!” Process process = null; try { process = Runtime.getRuntime().exec("ipconfig /all"); } catch (IOException e) { e.printSt
用户1154259
2018/01/17
1.5K0
Process API 指南-Java快速进阶教程
它所指的进程是一个正在执行的应用程序。Process类提供与这些进程交互的方法,包括提取输出、执行输入、监视生命周期、检查退出状态以及销毁(终止)它。
jack.yang
2025/04/05
1270
java:执行linux sudo命令
版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net/10km/article/details/78913746
10km
2019/05/25
6.4K1
java执行和停止Logcat命令及多线程实现
本人在使用UiAutomator的时候,想多写一个自动收集手机log的方法,使用runtime类执行了adb logcat的方法,但是一直找不到好的方法结束这个线程,网上说有kill pid的,但是这个操作起来略微麻烦了。自己也想了一个destroy线程的方法,一直不好用。提示错误信息如下:
FunTester
2019/08/14
1.7K0
Java 使用Runtime在一个Java程序中启动和关闭另一个Java程序
重点是Java启动的process,不能直接执行java、jps等命令,也获取不到环境变量,会报command not found
heasy3
2020/08/02
2.6K0
UiAutomator测试中如何恢复手机输入法
本人在使用UiAutomator测试的时候,需要用到utf7输入法,每次执行之前都会切换到utf7输入法,然后每次执行结束之后再切换到正常输入法,由于测试机器比较多,所以写了一个自动切换到其他任意输入法的方法。分享代码,供大家参考。
FunTester
2019/08/27
9450
Java执行Shell命令的方式
Java可以使用Runtime和ProcessBuilder两种方式执行Shell命令。
很酷的站长
2023/09/24
3.7K0
Java执行Shell命令的方式
RunNiFi.java 源码解读
RunNiFi类是由 nifi.sh脚本执行java命令指定的主类,RunNiFi类主要是干一些 查找文件,接受脚本指令,启动停止NIFI进程(主类 org.apache.nifi.NiFi),自动重启NIFI,发送NIFI通知等等操作;关于代码的详细解读都在注释当中,可以从 main方法下自行跟踪阅读(自己跟着源码逻辑读更好):
@阿诚
2020/09/01
1.3K0
相关推荐
java Runtime.exec()执行shell/cmd命令:常见的几种陷阱与一种完善实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验