admin管理员组

文章数量:1032071

如何在 Java 中运行 shell 命令

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运行复制
boolean isWindows = System.getProperty("os.name")
  .toLowerCase().startsWith("windows");Copy

3. 输入和输出

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

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

代码语言:javascript代码运行次数:0运行复制
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运行复制
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运行复制
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运行复制
ProcessBuilder builder = new ProcessBuilder();
if (isWindows) {
    buildermand("cmd.exe", "/c", "dir");
} else {
    buildermand("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 删除对象进程javashell操作系统

如何在 Java 中运行 shell 命令

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运行复制
boolean isWindows = System.getProperty("os.name")
  .toLowerCase().startsWith("windows");Copy

3. 输入和输出

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

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

代码语言:javascript代码运行次数:0运行复制
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运行复制
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运行复制
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运行复制
ProcessBuilder builder = new ProcessBuilder();
if (isWindows) {
    buildermand("cmd.exe", "/c", "dir");
} else {
    buildermand("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 删除对象进程javashell操作系统

本文标签: 如何在 Java 中运行 shell 命令