{"id":13438605,"url":"https://github.com/hniksic/rust-subprocess","last_synced_at":"2026-03-17T16:14:53.776Z","repository":{"id":15907698,"uuid":"78962568","full_name":"hniksic/rust-subprocess","owner":"hniksic","description":"Execution of and interaction with external processes and pipelines","archived":false,"fork":false,"pushed_at":"2026-02-08T13:42:25.000Z","size":888,"stargazers_count":450,"open_issues_count":1,"forks_count":45,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-02-08T20:25:39.036Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","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/hniksic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-01-14T19:43:04.000Z","updated_at":"2026-02-08T13:42:29.000Z","dependencies_parsed_at":"2024-06-18T16:50:04.412Z","dependency_job_id":"e3ba2038-aff2-4172-a24c-168d7d6c1dba","html_url":"https://github.com/hniksic/rust-subprocess","commit_stats":{"total_commits":339,"total_committers":16,"mean_commits":21.1875,"dds":0.06784660766961648,"last_synced_commit":"5e89ac093f378bcfc03c69bdb1b4bcacf4313ce4"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/hniksic/rust-subprocess","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hniksic%2Frust-subprocess","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hniksic%2Frust-subprocess/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hniksic%2Frust-subprocess/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hniksic%2Frust-subprocess/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hniksic","download_url":"https://codeload.github.com/hniksic/rust-subprocess/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hniksic%2Frust-subprocess/sbom","scorecard":{"id":466949,"data":{"date":"2025-08-11","repo":{"name":"github.com/hniksic/rust-subprocess","commit":"18ba33eab09174a055340e10e7c235f9182667aa"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":3,"reason":"Found 8/22 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE-APACHE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE-APACHE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 16 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T12:47:26.525Z","repository_id":15907698,"created_at":"2025-08-19T12:47:26.525Z","updated_at":"2025-08-19T12:47:26.525Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30626948,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T14:16:03.965Z","status":"ssl_error","status_checked_at":"2026-03-17T14:16:03.380Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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-07-31T03:01:06.802Z","updated_at":"2026-03-17T16:14:53.767Z","avatar_url":"https://github.com/hniksic.png","language":"Rust","funding_links":[],"categories":["Libraries","Rust","库 Libraries","库"],"sub_categories":["Command-line","命令行 Command-line","命令行"],"readme":"# subprocess\n\n[![crates.io](https://img.shields.io/crates/v/subprocess.svg)](https://crates.io/crates/subprocess)\n[![CI](https://github.com/hniksic/rust-subprocess/actions/workflows/ci.yml/badge.svg)](https://github.com/hniksic/rust-subprocess/actions/workflows/ci.yml)\n[![docs.rs](https://docs.rs/subprocess/badge.svg)](https://docs.rs/subprocess)\n\nThe `subprocess` crate makes it convenient to execute and interact with external processes\nand pipelines.  It is [hosted on crates.io](https://crates.io/crates/subprocess), with\n[API documentation on docs.rs](https://docs.rs/subprocess/).\n\nThe crate has minimal dependencies (only `libc` on Unix and `winapi` on Windows), and is\ntested on Linux, macOS, and Windows.\n\nIf you're upgrading from version 0.2, see the [migration guide](MIGRATION.md).\n\n## Why subprocess?\n\nCompared to [`std::process`](https://doc.rust-lang.org/std/process/index.html), the crate\nprovides additional features:\n\n* **OS-level pipelines** using the `|` operator: `Exec::cmd(\"find\") | \n  Exec::cmd(\"grep\").arg(r\"\\.py$\") | Exec::cmd(\"wc\")`. There is no difference between\n  interacting with pipelines and with a single process.\n\n* **Capture and communicate** [family of\n  methods](https://docs.rs/subprocess/latest/subprocess/struct.Job.html#method.capture)\n  for deadlock-free capturing of subprocess output/error, while simultaneously feeding\n  data to its standard input.  Capturing supports optional timeout and read size limit.\n\n* **Flexible redirection** options, such as connecting standard input to arbitrary data\n  sources, and merging output streams like shell's `2\u003e\u00261` and `1\u003e\u00262` operators.\n\n* **Non-blocking and timeout methods** to wait on the process: `subprocess` provides\n  timeout variants of its methods, such as\n  [`wait_timeout()`](https://docs.rs/subprocess/latest/subprocess/struct.Job.html#method.wait_timeout),\n  [`join_timeout()`](https://docs.rs/subprocess/latest/subprocess/struct.Job.html#method.join_timeout)\n  and\n  [`capture_timeout()`](https://docs.rs/subprocess/latest/subprocess/struct.Job.html#method.capture_timeout).\n\n* Various conveniences, such as `checked()` to flag non-zero exit status as error,\n  thread-safe and cloneable process handle with `\u0026self` methods, support for `setpgid()`\n  on individual commands and on the pipeline, and many others.\n\n## API Overview\n\nThe API consists of two main components:\n\n* **[`Exec`](https://docs.rs/subprocess/latest/subprocess/struct.Exec.html) /\n  [`Pipeline`](https://docs.rs/subprocess/latest/subprocess/struct.Pipeline.html)** -\n  builder-pattern API for configuring processes and pipelines.  Once configured,\n  [`start()`](https://docs.rs/subprocess/latest/subprocess/struct.Exec.html#method.start)\n  starts the process or pipeline. Includes convenience methods like\n  [`join()`](https://docs.rs/subprocess/latest/subprocess/struct.Exec.html#method.join)\n  and\n  [`capture()`](https://docs.rs/subprocess/latest/subprocess/struct.Exec.html#method.capture)\n  that start, collect results, and wait for the process to finish in one call.\n\n* **[`Job`](https://docs.rs/subprocess/latest/subprocess/struct.Job.html)** - interacts\n  with a started process or pipeline, returned by\n  [`start()`](https://docs.rs/subprocess/latest/subprocess/struct.Exec.html#method.start).\n  It holds the pipe files (`stdin`, `stdout`, `stderr`) and has methods like `capture()`\n  for interacting with them. It contains a list of `Process` handles and enables batch\n  operations over processes like `wait()` and `terminate()`.\n\n- **[`Process`](https://docs.rs/subprocess/latest/subprocess/struct.Process.html)** - a\n  cheaply cloneable handle to a single running process. It provides `pid()`, `wait()`,\n  `poll()`, `terminate()`, and `kill()`. Its methods take `\u0026self`, so you can use them on\n  `Process` shared across threads.\n\n## Examples\n\n### Execution\n\nExecute a command and wait for it to complete:\n\n```rust\nExec::cmd(\"umount\").arg(dirname).checked().join()?;\n```\n\n`join()` starts the command and waits for it to finish, returning the exit\nstatus. `checked()` ensures an error is returned for non-zero exit status.\n\nTo prevent quoting issues and shell injection attacks, `subprocess` doesn't spawn a shell\nunless explicitly requested.  To execute a command through the OS shell, use\n`Exec::shell`:\n\n```rust\nExec::shell(\"shutdown -h now\").join()?;\n```\n\n### Capturing output\n\nCapture the stdout and stderr of a command, and use the stdout:\n\n```rust\nlet rustver = Exec::shell(\"rustc --version\").capture()?.stdout_str();\n```\n\nCapture stdout and stderr merged together:\n\n```rust\nlet out_and_err = Exec::cmd(\"cargo\").arg(\"check\")\n    .stderr(Redirection::Merge)  // 2\u003e\u00261\n    .capture()?\n    .stdout_str();\n```\n\n`capture()` can simultaneously feed data to stdin and read stdout/stderr, avoiding the\ndeadlock that would result from doing these sequentially:\n\n```rust\nlet lines = Exec::cmd(\"sqlite3\")\n    .arg(db_path)\n    .stdin(\"SELECT name FROM users WHERE active = 1;\")\n    .capture()?\n    .stdout_str();\n```\n\n### Pipelines\n\nCreate pipelines using the `|` operator:\n\n```rust\nlet top_mem = (Exec::cmd(\"ps\").args(\u0026[\"aux\"])\n    | Exec::cmd(\"sort\").args(\u0026[\"-k4\", \"-rn\"])\n    | Exec::cmd(\"head\").arg(\"-5\"))\n    .capture()?\n    .stdout_str();\n```\n\nPipeline supports the same methods for interacting with the subprocess as with a single\nstarted command.\n\n### Streaming\n\nGet stdout as an object that implements `std::io::Read` (like C's `popen`):\n\n```rust\nlet stream = Exec::cmd(\"find\").arg(\"/\").stream_stdout()?;\n// Use stream.read_to_string(), BufReader::new(stream).lines(), etc.\n```\n\n### Arbitrary input\n\n`stdin()` doesn't accept just static strings, you can give it any owned data (such as in a\nmemory-mapped file or shared `bytes::Bytes` container), or generate it lazily:\n\n```rust\nuse subprocess::InputData;\n\n// send owned bytes\nlet bytes = bytes::Bytes::from(\"Hello world\");\nlet gzipped_bytes = Exec::cmd(\"gzip\")\n    .stdin(InputData::from_bytes(bytes))\n    .capture()?\n    .stdout;\n\n// send a gigabyte of zeros\nlet lazy_source = std::io::repeat(0).take(1_000_000_000);\nlet gzipped_stream = Exec::cmd(\"gzip\")\n    .stdin(InputData::from_reader(lazy_source))\n    .stream_stdout()?;\n```\n\nThe data is streamed to the subprocess in chunks.\n\n### Timeout\n\nCapture with timeout:\n\n```rust\nlet response = Exec::cmd(\"curl\").arg(\"-s\").arg(url)\n    .stdout(Redirection::Pipe)\n    .start()?\n    .capture_timeout(Duration::from_secs(10))?\n    .stdout_str();\n```\n\n`communicate()` can be used for more sophisticated control over timeouts, such as reading\nwith a time or size limit:\n\n```rust\nlet mut comm = Exec::cmd(\"ping\").arg(\"example.com\").communicate()?;\nlet (out, _) = comm\n    .limit_time(Duration::from_secs(5))\n    .read_string()?;\n```\n\n### Termination\n\nGive the process some time to run, then terminate if needed:\n\n```rust\nlet job = Exec::cmd(\"sleep\").arg(\"10\").start()?;\nmatch job.wait_timeout(Duration::from_secs(1))? {\n    Some(status) =\u003e println!(\"finished: {:?}\", status),\n    None =\u003e {\n        job.terminate()?;\n        job.wait()?;\n    }\n}\n```\n\n## License\n\n`subprocess` is distributed under the terms of both the MIT license and the Apache License\n(Version 2.0).  See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for\ndetails.  Contributing changes is assumed to signal agreement with these licensing terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhniksic%2Frust-subprocess","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhniksic%2Frust-subprocess","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhniksic%2Frust-subprocess/lists"}