#shell #helper #script #write #tasks #process #command

bin+lib rust-shell

用于在 rust 中编写类似任务的 shell 脚本的 std::process::Command 辅助库

1 个不稳定版本

使用旧的 Rust 2015

0.2.0 2022 年 12 月 6 日
0.1.1 2022 年 12 月 6 日
0.1.0 2022 年 12 月 6 日

#162 in #tasks


用于 justjs

MIT 许可证

35KB
626

Rust shell - 用 rust 编写的 shell 脚本。

这不是一个官方支持的 Google 产品

Rust shell 是 std::process::Command 的辅助库,用于在 rust 中编写类似任务的 shell 脚本。该库仅在类 Unix 操作系统上运行。

运行命令

run! 宏创建一个 ShellCommand 实例,您可以通过 run() 方法运行它。

#[macro_use] extern crate shell;

// Run command by cmd! macro
cmd!("echo Hello rust shell!").run().unwrap();

// Contain white space or non-alphabetical characters
cmd!("echo \"%$#\"").run().unwrap();

// Pass an argument
let name = "shell";
cmd!("echo Hello rust {}!", name).run().unwrap();

// Extract environment variable
cmd!("echo HOME is $HOME").run().unwrap();

ShellResult

ShellCommand#run() 的返回值是 ShellResult,只有在命令成功运行且其执行代码为 0 时才为 Ok(_),因此您可以使用 ? 操作符来检查命令是否成功退出。

#[macro_use] extern crate shell;
use shell::ShellResult;

fn shell_function() -> ShellResult {
  cmd!("echo Command A").run()?;
  cmd!("echo Command B").run()?;
  shell::ok()
}

输出字符串

ShellCommand 有一个简写来获取 stdout 作为 UTF8 字符串。

#[macro_use] extern crate shell;

assert_eq!(cmd!("echo OK").stdout_utf8().unwrap(), "OK\n");

Spawn

ShellCommand 有 spawn() 方法,它异步运行命令并返回 ShellChild

#[macro_use] extern crate shell;
extern crate libc;
use shell::ShellResultExt;

// Wait
let child = cmd!("sleep 2").spawn().unwrap();
child.wait().unwrap();

// Signal
let child = cmd!("sleep 2").spawn().unwrap();
child.signal(libc::SIGINT);
let result = child.wait();
assert!(result.is_err(), "Should be error as it exits with a signal");
assert!(result.status().is_ok(), "Still able to obtain status");

线程

如果您想异步运行一系列命令,shell::spawn 会创建一个线程以及 std::thread::spawn,但它返回 ShellHandle 包装 std::thread::JoinHandle

ShellHandle#signal() 用于向线程上运行的进程发送信号。它还通过在 ShellComamnd::run() 中停止启动新进程来在该线程上。

#[macro_use] extern crate shell;
extern crate libc;
use shell::ShellResult;
use shell::ShellResultExt;

let handle = shell::spawn(|| -> ShellResult {
  cmd!("sleep 3").run()
});
handle.signal(libc::SIGINT);
let result = handle.join().unwrap();
assert!(result.is_err(), "Should be error as it exits with a signal");
assert!(result.status().is_ok(), "Still able to obtain status");

信号处理

trap_signal_and_wait_children() 开始监视 SIGINT 和 SIGTERM 信号,并在接收到这些信号时等待所有子进程退出。在启动任何新线程之前需要调用此函数。

extern crate shell;
shell::trap_signal_and_wait_children().unwrap();

访问底层对象

ShellComamnd 包装了 std::process::Command,而 ShellChild 包装了 std::process::Child。这两个底层对象都可通过公共字段访问。

#[macro_use] extern crate shell;
use std::process::Stdio;
use std::io::Read;

// Access std::process::Command.
let mut shell_command = cmd!("echo OK");
{
  let mut command = &mut shell_command.command;
  command.stdout(Stdio::piped());
}

// Access std::process::Child.
let shell_child = shell_command.spawn().unwrap();
{
  let mut lock = shell_child.0.write().unwrap();
  let mut child = &mut lock.as_mut().unwrap().child;
  let mut str = String::new();
  child.stdout.as_mut().unwrap().read_to_string(&mut str);
}
shell_child.wait().unwrap();

许可证

Apatch 2 许可证

依赖关系

~4.5MB
~95K SLoC