5 个版本
0.2.1 | 2024年7月1日 |
---|---|
0.2.0 |
|
0.1.4 | 2024年6月13日 |
#198 在 并发
46KB
776 行
Creche
配置、运行和监视单个子进程或整个进程管道。将这些进程的文件描述符重定向到和从这些进程。控制环境变量。
Creche 是标准库中的 Command
和其他相关功能的替代品。
目标
- 最小依赖
- 没有宏,只有常规 Rust 语法
- 保持简单易用,同时不牺牲可配置性
限制
- 仅限 Linux
- 不支持
nostd
- 尚未处理子进程权限/能力
- 尚未支持异步
如何使用
ChildBuilder
和 SimplePipelineBuilder
类型是顶级导出,因此许多常见用例都可以通过简单的 use
use creche::*;
阅读 变更日志 了解 API 的重大更改。
示例
将 cat
的输出读取到 String
// configure the child process
let mut cmd = ChildBuilder::new("cat");
cmd.arg("somefile")
.redirect21(); // redirect stderr to stdout
let read_fd = cmd.pipe_from_stdout();
// run it
let mut child = cmd.spawn();
// read stdout from the child process
let f = std::fs::File::from(read_fd);
let output = std::io::read_to_string(f)?;
println!("output is: {:?}", output);
println!("exit status: {:?}", child.wait());
向子进程写入数据
let mut cmd = creche::ChildBuilder::new("tr");
cmd.arg("[:lower:]")
.arg("[:upper:]");
let write_fd = cmd.pipe_to_stdin();
let child = cmd.spawn();
// write some data
let mut f = std::fs::File::from(write_fd);
writeln!(f, "this is a test message");
// don't forget to close your fd. Or at least .flush() the thing.
drop(f);
println!("child exit: {:?}", child.wait());
设置 fzf 在仅包含 PATH、HOME 和 FZF_DEFAULT_COMMAND 的环境中运行。然后运行它并获取其输出
// configure the environment
let mut env = envconfig::EnvironmentBuilder::new();
env.keep("PATH")
.set("HOME", "/etc")
// Note: $HOME is expanded in the shell spawned by fzf.
// It's not creche magic.
.set("FZF_DEFAULT_COMMAND", "ls -1 $HOME");
// configure the child process
let mut cmd = ChildBuilder::new("fzf");
cmd.arg("-m")
.arg(r#"--preview=bat $HOME/{}"#)
.set_env(env.realize());
let read_fd = cmd.pipe_from_stdout();
// run it
let child = cmd.spawn();
// read the result
let mut f = std::fs::File::from(read_fd);
let output = std::io::read_to_string(f)?;
println!("output is: {:?}", output);
println!("exit status: {:?}", child.wait());
将 ls
的输出通过 sort
通过 tr
。将所有这些的 stderr 重定向到 /dev/null
let mut ls_cmd = ChildBuilder::new("ls");
ls_cmd.arg("-1");
let mut sort_cmd = ChildBuilder::new("sort");
sort_cmd.arg("-r");
let mut tr_cmd = ChildBuilder::new("tr");
tr_cmd.arg("[:lower:]");
tr_cmd.arg("[:upper:]");
let mut pipeline = SimplePipelineBuilder::new();
let mut children = pipeline
.add_builder(ls_cmd)
.add_builder(sort_cmd)
.add_builder(tr_cmd)
.quiet()
.spawn();
println!("{:?}", children.wait());
在另一个线程中发送 SIGTERM 信号并阻塞等待子进程的 .wait()
// sleep for a few seconds
let mut cmd = ChildBuilder::new("sleep");
cmd.arg("6");
println!("sleeping for six seconds");
let child = cmd.spawn();
// get a "handle" to the child process so that we may signal it
let handle = child.get_handle();
// start a thread that sends SIGTERM after a short pause
std::thread::spawn( move || {
std::thread::sleep(std::time::Duration::from_secs(2));
println!("sending SIGTERM from thread");
_ = handle.terminate();
});
// collect the child exit status
println!("child exit: {:?}", child.wait());
依赖关系
~1.5MB
~35K SLoC