Module java.base
Package java.lang

Class ProcessBuilder

java.lang.Object
java.lang.ProcessBuilder

public final class ProcessBuilder extends Object
该类用于创建操作系统进程。

每个ProcessBuilder实例管理一组进程属性。 start()方法使用这些属性创建一个新的Process实例。可以重复从同一实例调用start()方法,以创建具有相同或相关属性的新子进程。

可以调用startPipeline方法来创建一个新进程管道,该管道将每个进程的输出直接发送到下一个进程。每个进程都具有其相应ProcessBuilder的属性。

每个进程构建器管理这些进程属性:

  • 一个命令,一个字符串列表,表示要调用的外部程序文件及其参数(如果有)。哪些字符串列表表示有效的操作系统命令取决于系统。例如,每个概念参数在此列表中都是一个元素是常见的,但有些操作系统期望程序自行对命令行字符串进行标记化 - 在这样的系统上,Java实现可能要求命令包含确切的两个元素。
  • 一个环境,这是一个从变量的系统相关映射。初始值是当前进程的环境的副本(参见System.getenv())。
  • 一个工作目录。默认值是当前进程的当前工作目录,通常是由系统属性user.dir命名的目录。
  • 一个标准输入。默认情况下,子进程从管道读取输入。Java代码可以通过Process.getOutputStream()返回的输出流访问此管道。但是,标准输入可能会被重定向到另一个源,使用redirectInput。在这种情况下,Process.getOutputStream()将返回一个空输出流,对于该流:
    • write方法总是抛出IOException
    • close方法不执行任何操作
  • 一个标准输出标准错误的目的地。默认情况下,子进程将标准输出和标准错误写入管道。Java代码可以通过Process.getInputStream()Process.getErrorStream()返回的输入流访问这些管道。但是,标准输出和标准错误可能会被重定向到其他目的地,使用redirectOutputredirectError。在这种情况下,Process.getInputStream()和/或Process.getErrorStream()将返回一个空输入流,对于该流:
  • 一个redirectErrorStream属性。最初,此属性为false,这意味着子进程的标准输出和错误输出被发送到两个单独的流,可以使用Process.getInputStream()Process.getErrorStream()方法访问这些流。

    如果将值设置为true,则:

    • 标准错误与标准输出合并,并始终发送到相同的目的地(这使得更容易将错误消息与相应的输出相关联)
    • 标准错误和标准输出的共同目的地可以使用redirectOutput重定向
    • 在创建子进程时,redirectError方法设置的任何重定向都将被忽略
    • Process.getErrorStream()返回的流将始终是一个空输入流

修改进程构建器的属性将影响随后由该对象的start()方法启动的进程,但永远不会影响先前启动的进程或Java进程本身。

大多数错误检查由start()方法执行。可以修改对象的状态,使start()失败。例如,将命令属性设置为空列表不会引发异常,除非调用start()

请注意,此类未同步。如果多个线程同时访问ProcessBuilder实例,并且至少有一个线程结构上修改了其中一个属性,则必须在外部进行同步。

启动使用默认工作目录和环境的新进程很容易:

 
 Process p = new ProcessBuilder("myCommand", "myArg").start();
 

以下是一个示例,启动具有修改后的工作目录和环境的进程,并将标准输出和错误重定向到追加到日志文件中:

 
 ProcessBuilder pb =
   new ProcessBuilder("myCommand", "myArg1", "myArg2");
 Map<String, String> env = pb.environment();
 env.put("VAR1", "myValue");
 env.remove("OTHERVAR");
 env.put("VAR2", env.get("VAR1") + "suffix");
 pb.directory(new File("myDir"));
 File log = new File("log");
 pb.redirectErrorStream(true);
 pb.redirectOutput(Redirect.appendTo(log));
 Process p = pb.start();
 assert pb.redirectInput() == Redirect.PIPE;
 assert pb.redirectOutput().file() == log;
 assert p.getInputStream().read() == -1;
 

要使用显式一组环境变量启动进程,请在添加环境变量之前首先调用Map.clear()

除非另有说明,在此类中将null参数传递给构造函数或方法将导致抛出NullPointerException

自版本:
1.5
  • Constructor Details

    • ProcessBuilder

      public ProcessBuilder(List<String> command)
      使用指定的操作系统程序和参数构造进程构建器。此构造函数不会复制command列表。对列表的后续更新将反映在进程构建器的状态中。不检查command是否对应于有效的操作系统命令。
      参数:
      command - 包含程序及其参数的列表
    • ProcessBuilder

      public ProcessBuilder(String... command)
      使用指定的操作系统程序和参数构造进程构建器。这是一个方便的构造函数,将命令设置为包含与command数组中相同字符串的字符串列表,顺序相同。不检查command是否对应于有效的操作系统命令。
      参数:
      command - 包含程序及其参数的字符串数组
  • Method Details

    • command

      public ProcessBuilder command(List<String> command)
      设置此进程构建器的操作系统程序和参数。此方法不会复制command列表。对列表的后续更新将反映在进程构建器的状态中。不检查command是否对应于有效的操作系统命令。
      参数:
      command - 包含程序及其参数的列表
      返回:
      此进程构建器
    • command

      public ProcessBuilder command(String... command)
      设置此进程构建器的操作系统程序和参数。这是一个方便的方法,将命令设置为包含与command数组中相同字符串的字符串列表,顺序相同。不检查command是否对应于有效的操作系统命令。
      参数:
      command - 包含程序及其参数的字符串数组
      返回:
      此进程构建器
    • command

      public List<String> command()
      返回此进程构建器的操作系统程序和参数。返回的列表不是副本。对列表的后续更新将反映在此进程构建器的状态中。
      返回:
      此进程构建器的程序及其参数
    • environment

      public Map<String,String> environment()
      返回此进程构建器环境的字符串映射视图。每当创建进程构建器时,环境都会初始化为当前进程环境的副本(参见System.getenv())。随后由此对象的start()方法启动的子进程将使用此映射作为它们的环境。

      返回的对象可以使用普通的Map操作进行修改。这些修改将对通过start()方法启动的子进程可见。两个ProcessBuilder实例始终包含独立的进程环境,因此对返回的映射的更改永远不会反映在任何其他ProcessBuilder实例或System.getenv返回的值中。

      如果系统不支持环境变量,则返回一个空映射。

      返回的映射不允许空键或值。尝试插入或查询空键或值的存在将抛出NullPointerException。尝试查询不是String类型的键或值的存在将抛出ClassCastException

      返回的映射的行为取决于系统。系统可能不允许修改环境变量,或者可能禁止某些变量名称或值。因此,如果操作系统不允许修改映射,则尝试修改映射可能会因为不被操作系统允许而失败,导致抛出UnsupportedOperationExceptionIllegalArgumentException

      由于环境变量名称和值的外部格式是系统相关的,因此它们与Java的Unicode字符串之间可能没有一一对应的映射。尽管如此,该映射的实现方式使得未被Java代码修改的环境变量在子进程中具有未修改的本机表示。

      返回的映射及其集合视图可能不遵守Object.equals(java.lang.Object)Object.hashCode()方法的一般契约。

      返回的映射通常在所有平台上区分大小写。

      如果存在安全管理器,则将使用其checkPermission方法调用RuntimePermission("getenv.*")权限。这可能导致抛出SecurityException

      在向Java子进程传递信息时,通常优先使用系统属性而不是环境变量。

      返回:
      此进程构建器的环境
      抛出:
      SecurityException - 如果存在安全管理器并且其checkPermission方法不允许访问进程环境
      参见:
    • directory

      public File directory()
      返回此进程构建器的工作目录。随后由此对象的start()方法启动的子进程将使用此目录作为它们的工作目录。返回值可能为null -- 这意味着使用当前Java进程的工作目录,通常是由系统属性user.dir命名的目录,作为子进程的工作目录。
      返回:
      此进程构建器的工作目录
    • directory

      public ProcessBuilder directory(File directory)
      设置此进程构建器的工作目录。随后由此对象的start()方法启动的子进程将使用此目录作为它们的工作目录。参数可能为null -- 这意味着使用当前Java进程的工作目录,通常是由系统属性user.dir命名的目录,作为子进程的工作目录。
      参数:
      directory - 新的工作目录
      返回:
      此进程构建器
    • redirectInput

      public ProcessBuilder redirectInput(ProcessBuilder.Redirect source)
      设置此进程构建器的标准输入源。随后由此对象的start()方法启动的子进程将从此源获取它们的标准输入。

      如果源为Redirect.PIPE(初始值),则子进程的标准输入可以使用Process.getOutputStream()返回的输出流写入。如果源设置为任何其他值,则Process.getOutputStream()将返回一个空输出流

      参数:
      source - 新的标准输入源
      返回:
      此进程构建器
      抛出:
      IllegalArgumentException - 如果重定向不对应于有效的数据源,即,具有类型WRITEAPPEND
      自:
      1.7
    • redirectOutput

      public ProcessBuilder redirectOutput(ProcessBuilder.Redirect destination)
      设置此进程构建器的标准输出目的地。随后由此对象的start()方法启动的子进程将将它们的标准输出发送到此目的地。

      如果目的地为Redirect.PIPE(初始值),则子进程的标准输出可以使用Process.getInputStream()返回的输入流读取。如果目的地设置为任何其他值,则Process.getInputStream()将返回一个空输入流

      参数:
      destination - 新的标准输出目的地
      返回:
      此进程构建器
      抛出:
      IllegalArgumentException - 如果重定向不对应于有效的数据目的地,即,具有类型READ
      自:
      1.7
    • redirectError

      public ProcessBuilder redirectError(ProcessBuilder.Redirect destination)
      设置此进程构建器的标准错误目的地。随后由此对象的start()方法启动的子进程将将它们的标准错误发送到此目的地。

      如果目的地为Redirect.PIPE(初始值),则子进程的错误输出可以使用Process.getErrorStream()返回的输入流读取。如果目的地设置为任何其他值,则Process.getErrorStream()将返回一个空输入流

      如果已将redirectErrorStream属性设置为true,则此方法设置的重定向将不起作用。

      参数:
      destination - 新的标准错误目的地
      返回:
      此进程构建器
      抛出:
      IllegalArgumentException - 如果重定向不对应于有效的数据目的地,即,具有类型READ
      自:
      1.7
    • redirectInput

      public ProcessBuilder redirectInput(File file)
      将此进程构建器的标准输入源设置为文件。

      这是一个便利方法。形式为redirectInput(file)的调用与调用redirectInput(Redirect.from(file))的行为完全相同。

      参数:
      file - 新的标准输入源
      返回:
      此进程构建器
      自:
      1.7
    • redirectOutput

      public ProcessBuilder redirectOutput(File file)
      将此进程构建器的标准输出目的地设置为文件。

      这是一个便利方法。形式为redirectOutput(file)的调用与调用redirectOutput(Redirect.to(file))的行为完全相同。

      参数:
      file - 新的标准输出目的地
      返回:
      此进程构建器
      自:
      1.7
    • redirectError

      public ProcessBuilder redirectError(File file)
      将此进程构建器的标准错误目的地设置为文件。

      这是一个便利方法。形式为redirectError(file)的调用与调用redirectError(Redirect.to(file))的行为完全相同。

      参数:
      file - 新的标准错误目的地
      返回:
      此进程构建器
      自:
      1.7
    • redirectInput

      public ProcessBuilder.Redirect redirectInput()
      返回此进程构建器的标准输入源。随后由此对象的start()方法启动的子进程将从此源获取它们的标准输入。初始值为Redirect.PIPE
      返回:
      此进程构建器的标准输入源
      自:
      1.7
    • redirectOutput

      public ProcessBuilder.Redirect redirectOutput()
      返回此进程构建器的标准输出目的地。随后由此对象的 start() 方法启动的子进程将其标准输出重定向到此目的地。初始值为 Redirect.PIPE
      返回:
      此进程构建器的标准输出目的地
      自:
      1.7
    • redirectError

      public ProcessBuilder.Redirect redirectError()
      返回此进程构建器的标准错误目的地。随后由此对象的 start() 方法启动的子进程将其标准错误重定向到此目的地。初始值为 Redirect.PIPE
      返回:
      此进程构建器的标准错误目的地
      自:
      1.7
    • inheritIO

      public ProcessBuilder inheritIO()
      设置子进程标准I/O的源和目的地与当前Java进程的相同。

      这是一个便利方法。调用形式

       
       pb.inheritIO()
       
      的行为与调用
       
       pb.redirectInput(Redirect.INHERIT)
         .redirectOutput(Redirect.INHERIT)
         .redirectError(Redirect.INHERIT)
       
      完全相同。这提供了与大多数操作系统命令解释器或标准C库函数 system() 等效的行为。
      返回:
      此进程构建器
      自:
      1.7
    • redirectErrorStream

      public boolean redirectErrorStream()
      指示此进程构建器是否合并标准错误和标准输出。

      如果此属性为 true,则由此对象的 start() 方法随后启动的子进程生成的任何错误输出将与标准输出合并,以便可以使用 Process.getInputStream() 方法读取两者。这样可以更容易地将错误消息与相应的输出关联起来。初始值为 false

      返回:
      此进程构建器的 redirectErrorStream 属性
    • redirectErrorStream

      public ProcessBuilder redirectErrorStream(boolean redirectErrorStream)
      设置此进程构建器的 redirectErrorStream 属性。

      如果此属性为 true,则由此对象的 start() 方法随后启动的子进程生成的任何错误输出将与标准输出合并,以便可以使用 Process.getInputStream() 方法读取两者。这样可以更容易地将错误消息与相应的输出关联起来。初始值为 false

      参数:
      redirectErrorStream - 新的属性值
      返回:
      此进程构建器
    • start

      public Process start() throws IOException
      使用此进程构建器的属性启动一个新进程。

      新进程将调用由 command() 给出的命令和参数,在由 directory() 给出的工作目录中,使用由 environment() 给出的进程环境。

      此方法检查命令是否是有效的操作系统命令。哪些命令是有效的取决于系统,但至少命令必须是一个非空的非空字符串列表。

      在某些操作系统上,启动进程可能需要一组最小的系统相关环境变量。因此,子进程可能会继承进程构建器的 environment() 中未提供的其他环境变量设置。最小的系统相关环境变量集可能会覆盖提供的环境中的值。

      如果存在安全管理器,则将其 checkExec 方法以此对象的 command 数组的第一个组件作为其参数进行调用。这可能导致抛出 SecurityException

      启动操作系统进程高度依赖于系统。可能出现的问题包括:

      • 未找到操作系统程序文件。
      • 拒绝访问程序文件。
      • 工作目录不存在。
      • 命令参数中存在无效字符,如NUL。

      在这种情况下将抛出异常。异常的确切性质取决于系统,但它将始终是 IOException 的子类。

      如果操作系统不支持创建进程,则会抛出 UnsupportedOperationException

      对此进程构建器的后续修改不会影响返回的 Process

      实现注意:
      在参考实现中,可以启用命令、参数、目录、堆栈跟踪和进程ID的日志记录。日志记录的信息可能包含敏感的安全信息,应仔细审查信息的潜在暴露。当系统记录器 java.lang.ProcessBuilder 的日志级别为 Level.DEBUGLevel.TRACE 时启用日志记录。当启用 Level.DEBUG 时,仅记录进程ID、目录、命令和堆栈跟踪。当启用 Level.TRACE 时,参数将与进程ID、目录、命令和堆栈跟踪一起包含在内。
      返回:
      用于管理子进程的新 Process 对象
      抛出:
      NullPointerException - 如果命令列表的元素为null
      IndexOutOfBoundsException - 如果命令是空列表(大小为 0
      SecurityException - 如果存在安全管理器且
      • checkExec 方法不允许创建子进程,或
      • 子进程的标准输入被从文件 重定向,并且安全管理器的 checkRead 方法拒绝对文件的读取访问,或
      • 子进程的标准输出或标准错误被 重定向到文件,并且安全管理器的 checkWrite 方法拒绝对文件的写入访问
      UnsupportedOperationException - 如果操作系统不支持创建进程
      IOException - 如果发生I/O错误
      参见:
    • startPipeline

      public static List<Process> startPipeline(List<ProcessBuilder> builders) throws IOException
      开始一个进程,为每个ProcessBuilder创建一个进程管道,通过它们的标准输出和标准输入流连接各个进程。每个ProcessBuilder的属性用于启动相应的进程,除了每个进程启动时,其标准输出被定向到下一个进程的标准输入。第一个进程的标准输入和最后一个进程的标准输出的重定向使用各自ProcessBuilder的重定向设置进行初始化。所有其他ProcessBuilder的重定向应该是Redirect.PIPE

      中间进程之间的所有输入和输出流都不可访问。除第一个进程外,所有进程的标准输入都是空输出流。除最后一个进程外,所有进程的标准输出都是空输入流

      每个ProcessBuilder的redirectErrorStream()应用于相应的进程。如果设置为true,错误流将写入与标准输出相同的流。

      如果启动任何进程抛出异常,则所有进程都将被强制销毁。

      startPipeline方法对每个ProcessBuilder执行与start()方法相同的检查。每个新进程调用相应进程构建器的command()给出的命令和参数,在由其directory()给出的工作目录中,使用由其environment()给出的进程环境。

      每个进程构建器的命令都会被检查是否是有效的操作系统命令。哪些命令是有效的取决于系统,但至少命令必须是一个非空的非空字符串列表。

      在某些操作系统上启动进程可能需要一组最小的系统相关环境变量。因此,子进程可能会继承除进程构建器的environment()中提供的值之外的其他环境变量设置。最小的系统相关环境变量集可能会覆盖环境中提供的值。

      如果存在安全管理器,则将使用每个进程构建器的command数组的第一个组件作为其参数调用其checkExec方法。这可能导致抛出SecurityException

      启动操作系统进程高度依赖于系统。可能出现的问题包括:

      • 未找到操作系统程序文件。
      • 拒绝访问程序文件。
      • 工作目录不存在。
      • 命令参数中存在无效字符,如NUL。

      在这种情况下将抛出异常。异常的确切性质取决于系统,但它将始终是IOException的子类。

      如果操作系统不支持创建进程,则会抛出UnsupportedOperationException

      对任何指定构建器的后续修改不会影响返回的Process

      API 注意:
      例如,在Unix兼容平台上计算文件层次结构中所有文件的唯一导入的数量:
      
       String directory = "/home/duke/src";
       ProcessBuilder[] builders = {
                    new ProcessBuilder("find", directory, "-type", "f"),
                    new ProcessBuilder("xargs", "grep", "-h", "^import "),
                    new ProcessBuilder("awk", "{print $2;}"),
                    new ProcessBuilder("sort", "-u")};
       List<Process> processes = ProcessBuilder.startPipeline(
               Arrays.asList(builders));
       Process last = processes.get(processes.size()-1);
       try (InputStream is = last.getInputStream();
               Reader isr = new InputStreamReader(is);
               BufferedReader r = new BufferedReader(isr)) {
           long count = r.lines().count();
       }
       
      实现注意:
      在参考实现中,可以启用每个创建的进程的日志记录,请参阅start()以获取详细信息。
      参数:
      builders - 一个ProcessBuilder的列表
      返回:
      从相应的ProcessBuilder启动的List<Process>
      抛出:
      IllegalArgumentException - 除第一个构建器的标准输入和最后一个构建器的标准输出之外的所有重定向都不是ProcessBuilder.Redirect.PIPE
      NullPointerException - 如果命令列表的元素为null,或者ProcessBuilder列表的元素为null,或者构建器参数为null
      IndexOutOfBoundsException - 如果命令是一个空列表(大小为0
      SecurityException - 如果存在安全管理器,并且
      • checkExec方法不允许创建子进程,或
      • 子进程的标准输入被从文件重定向,并且安全管理器的checkRead方法拒绝对文件的读取访问,或
      • 子进程的标准输出或标准错误被重定向到文件,并且安全管理器的checkWrite方法拒绝对文件的写访问
      UnsupportedOperationException - 如果操作系统不支持创建进程
      IOException - 如果发生I/O错误
      自:
      9