{"id":19674252,"url":"https://github.com/zeroturnaround/zt-exec","last_synced_at":"2025-05-14T18:03:11.976Z","repository":{"id":8622987,"uuid":"10266565","full_name":"zeroturnaround/zt-exec","owner":"zeroturnaround","description":"ZeroTurnaround Process Executor","archived":false,"fork":false,"pushed_at":"2024-03-15T20:33:23.000Z","size":412,"stargazers_count":894,"open_issues_count":9,"forks_count":110,"subscribers_count":41,"default_branch":"main","last_synced_at":"2025-04-13T10:54:17.066Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zeroturnaround.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.txt","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-05-24T13:06:36.000Z","updated_at":"2025-04-12T12:39:26.000Z","dependencies_parsed_at":"2024-01-03T01:23:03.097Z","dependency_job_id":"dbd6cae1-1632-44fb-bd9b-8fd429f8e6be","html_url":"https://github.com/zeroturnaround/zt-exec","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeroturnaround%2Fzt-exec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeroturnaround%2Fzt-exec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeroturnaround%2Fzt-exec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeroturnaround%2Fzt-exec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zeroturnaround","download_url":"https://codeload.github.com/zeroturnaround/zt-exec/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198452,"owners_count":22030964,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T17:17:42.026Z","updated_at":"2025-05-14T18:03:06.966Z","avatar_url":"https://github.com/zeroturnaround.png","language":"Java","readme":"ZT Process Executor\n================\n\n### Continuous Integration\n![Build Status](https://github.com/zeroturnaround/zt-exec/actions/workflows/maven.yml/badge.svg)\n\n### Quick Overview\n\nThe project was created to merge similar functionality of projects at [ZeroTurnaround](http://zeroturnaround.com/) into a single codebase.\nIt's designed to be powerful but still simple to use. By using a single class **ProcessExecutor**\nthe user gets the functionality from both **java.lang.ProcessBuilder** and [Apache Commons Exec](http://commons.apache.org/proper/commons-exec/).\n\n### Dependencies\n\n* Minimal required Java version is 6 (tested also with 8, 11 and 17).\n* The only 3rd-party dependency is [SLF4J](https://www.slf4j.org/).\n\n### Installation\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.zeroturnaround/zt-exec/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.zeroturnaround/zt-exec)\n\nThe project artifacts are available in [Maven Central Repository](https://search.maven.org/artifact/org.zeroturnaround/zt-exec/).\n\nTo include it in your maven project then you have to specify the dependency.\n\n```xml\n...\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.zeroturnaround\u003c/groupId\u003e\n    \u003cartifactId\u003ezt-exec\u003c/artifactId\u003e\n    \u003cversion\u003e1.12\u003c/version\u003e\n\u003c/dependency\u003e\n...\n```\n\n## Motivation\n\nThere are many approaches to take when running external processes from Java. There are the **JRE** options such as the **Runtime.exec()** and **ProcessBuilder**. Also there is the [Apache Commons Exec](http://commons.apache.org/proper/commons-exec/). Nevertheless we created yet another process library (**YAPL**). \n\nSome of the reasons for this crazy endeavour\n\n* Improved handling of streams\n * Reading/writing to streams\n * Redirecting stderr to stdout\n* Improved handling of timeouts\n* Improved checking of exit codes\n* Improved API\n * One liners for quite complex usecases\n * One liners to get process output into a String\n * Access to the **Process** object available\n * Support for async processes ( **Future** ) \n* Improved logging with [SLF4J API](http://www.slf4j.org/)\n* Support for multiple processes\n\n**Can zt-exec also kill processes?**\n\nNo. There is [zt-process-killer](https://github.com/zeroturnaround/zt-process-killer) for that.\n\n## Examples\n\n* Output is pumped to NullOutputStream\n\n```java\nnew ProcessExecutor().command(\"java\", \"-version\").execute();\n```\n\n\u003chr/\u003e\n\n* Returning the exit code\n* Output is pumped to NullOutputStream\n\n```java\nint exit = new ProcessExecutor().command(\"java\", \"-version\")\n                  .execute().getExitValue();\n```\n\n\u003chr/\u003e\n\n* Return output as UTF8 String\n\n```java\nString output = new ProcessExecutor().command(\"java\", \"-version\")\n                  .readOutput(true).execute()\n                  .outputUTF8();    \n```\n\n\u003chr/\u003e\n\n* Pumping the output to a logger\n\n```java\nnew ProcessExecutor().command(\"java\", \"-version\")\n      .redirectOutput(Slf4jStream.of(LoggerFactory.getLogger(getClass().getName() + \".MyProcess\")).asInfo()).execute();\n```\n\n\u003chr/\u003e\n\n* Pumping the output to a logger (short form for previous)\n\n```java\nnew ProcessExecutor().command(\"java\", \"-version\")\n      .redirectOutput(Slf4jStream.of(\"MyProcess\").asInfo()).execute();\n```\n\n\u003chr/\u003e\n\n* Pumping the output to the logger of the caller class\n\n```java\nnew ProcessExecutor().command(\"java\", \"-version\")\n      .redirectOutput(Slf4jStream.ofCaller().asInfo()).execute();\n```\n\n\u003chr/\u003e\n\n* Pumping the output to a logger\n* Returning output as UTF8 String\n\n```java\nString output = new ProcessExecutor().command(\"java\", \"-version\")\n        .redirectOutput(Slf4jStream.of(getClass()).asInfo())\n        .readOutput(true).execute().outputUTF8();\n```\n\n\u003chr/\u003e\n\n* Pumping the stderr to a logger\n* Returning the output as UTF8 String\n\n```java\nString output = new ProcessExecutor().command(\"java\", \"-version\")\n        .redirectError(Slf4jStream.of(getClass()).asInfo())\n        .readOutput(true).execute()\n        .outputUTF8();\n```\n\n\u003chr/\u003e\n\n* Running with a timeout of **60** seconds\n* Output pumped to NullOutputStream\n\n```java\ntry {\n  new ProcessExecutor().command(\"java\", \"-version\")\n        .timeout(60, TimeUnit.SECONDS).execute();\n}\ncatch (TimeoutException e) {\n  // process is automatically destroyed\n}\n```\n\n\u003chr/\u003e\n\n* Pumping output to another OutputStream\n\n```java\nOutputStream out = ...;\nnew ProcessExecutor().command(\"java\", \"-version\")\n      .redirectOutput(out).execute();\n```\n\n\u003chr/\u003e\n\n* Handling output line-by-line while process is running (Java 8+)\n\n```java\nnew ProcessExecutor().command(\"java\", \"-version\")\n    .redirectOutput(line -\u003e ...)\n    .execute();\n```\n\n\u003chr/\u003e\n\n* Handling output line-by-line while process is running (prior to Java 8)\n\n```java\nnew ProcessExecutor().command(\"java\", \"-version\")\n    .redirectOutput(new LogOutputStream() {\n      @Override\n      protected void processLine(String line) {\n        ...\n      }\n    })\n    .execute();\n```\n\n\u003chr/\u003e\n\n* Destroy the running process when VM exits\n* Output pumped to NullOutputStream\n\n```java\nnew ProcessExecutor().command(\"java\", \"-version\").destroyOnExit().execute();\n```\n\n\u003chr/\u003e\n\n* Run process with a specific environment variable\n* Output pumped to NullOutputStream\n\n```java\nnew ProcessExecutor().command(\"java\", \"-version\")\n    .environment(\"foo\", \"bar\").execute();\n```\n\n\u003chr/\u003e\n\n* Run process with a specific environment\n* Output pumped to NullOutputStream\n\n```java\nMap\u003cString, String\u003e env = ...\nnew ProcessExecutor().command(\"java\", \"-version\")\n    .environment(env).execute();\n```\n\n\u003chr/\u003e\n\n* Throw exception when wrong exit code\n* Output is pumped to NullOutputStream\n\n```java\ntry {\n  new ProcessExecutor().command(\"java\", \"-version\")\n        .exitValues(3).execute();\n}\ncatch (InvalidExitValueException e) {\n  System.out.println(\"Process exited with \" + e.getExitValue());\n}\n```\n\n\u003chr/\u003e\n\n* Throw exception when wrong exit code\n* Return output as UTF8 String \n\n```java\nString output;\nboolean success = false;\ntry {\n  output = new ProcessExecutor().command(\"java\", \"-version\")\n                .readOutput(true).exitValues(3)\n                .execute().outputUTF8();\n  success = true;\n}\ncatch (InvalidExitValueException e) {\n  System.out.println(\"Process exited with \" + e.getExitValue());\n  output = e.getResult().outputUTF8();\n}\n```\n\n\u003chr/\u003e\n\n* Starting process in the background\n* Output is pumped to NullOutputStream\n\n```java\nFuture\u003cProcessResult\u003e future = new ProcessExecutor()\n                                    .command(\"java\", \"-version\")\n                                    .start().getFuture();\n// do some stuff\nfuture.get(60, TimeUnit.SECONDS);\n```\n\n\u003chr/\u003e\n\n* Start process in the background\n* Return output as UTF8 String\n\n```java\nFuture\u003cProcessResult\u003e future = new ProcessExecutor()\n                                    .command(\"java\", \"-version\")\n                                    .readOutput(true)\n                                    .start().getFuture();\n// do some stuff\nString output = future.get(60, TimeUnit.SECONDS).outputUTF8();\n```\n","funding_links":[],"categories":["Projects","项目","Solutions"],"sub_categories":["Processes","流程"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeroturnaround%2Fzt-exec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzeroturnaround%2Fzt-exec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeroturnaround%2Fzt-exec/lists"}