5 个版本

使用旧的 Rust 2015

0.13.7 2023年12月22日
0.13.6 2022年11月29日
0.13.5 2021年2月4日
0.13.4 2020年4月13日
0.1.0 2017年5月30日

371命令行界面

Download history 237/week @ 2024-04-22 187/week @ 2024-04-29 256/week @ 2024-05-06 335/week @ 2024-05-13 203/week @ 2024-05-20 112/week @ 2024-05-27 144/week @ 2024-06-03 81/week @ 2024-06-10 149/week @ 2024-06-17 87/week @ 2024-06-24 49/week @ 2024-07-01 197/week @ 2024-07-08 120/week @ 2024-07-15 191/week @ 2024-07-22 185/week @ 2024-07-29 127/week @ 2024-08-05

628 每月下载量
8 crates 中使用

MIT 许可证

115KB
1.5K SLoC

duct_sh crates.io docs.rs

是构建由 shell 字符串组成的命令的 duct crate 的便利包装器。Duct 通常直接执行命令,而无需通过 shell。这可能是首选的,因为它避免了棘手的空白问题以及 shell 注入漏洞。然而,有时你需要访问更多奇特的 shell 功能(例如,shell 内置函数如 sourceexec,或使用 <() 的进程替换),而有时你只能运行一些 shell 代码。

在这些情况下,duct_sh 是一个“跨平台”的方式来运行 shell 命令,结合了 Duct 的所有常规功能。“跨平台”一词用引号括起来,因为 shell 代码必然是平台特定的。Unix 上的典型 Bourne-like shells 和 Windows 系统上的 cmd.exe shell 在很多方面都有共同之处,包括 |> 运算符,但当你开始查看细节时,它们很快就会分歧。因此,真正的跨平台程序应尽可能避免使用 shell 代码。

示例

// Execute a static string of shell code.
let output = duct_sh::sh("echo $MSG | sed s/i/a/").env("MSG", "hi").read()?;
assert_eq!(output, "ha");

// Execute a dynamic string of shell code. Note that this requires the
// "sh_dangerous" function. See the Security section below.
let arg = "hi";
let command = format!("echo {} | sed s/i/a/", arg);
let output = duct_sh::sh_dangerous(&command).read()?;
assert_eq!(output, "ha");

安全性

sh 函数仅限于静态字符串。sh_dangerous 函数做的是完全相同的事情,但它接受动态字符串。这个名字听起来很可怕,是因为它与 shell 注入相关的安全问题有关。考虑这个看起来无害的函数

fn echo_string(s: &str) {
    duct_sh::sh_dangerous(format!("echo {}", s)).run().unwrap();
}

此函数似乎在 s 是类似 "foo""foo bar" 这样的良好行为的字符串时正常工作。如果您尝试 "foo   bar",可能会注意到一些错误,因为这三个空格在输出中会合并成一个。但真正的问题是一个像 "; rm -rf /" 这样的字符串。产生的命令将打印一个换行符,然后尝试删除您的整个硬盘。任何类似 echo_string 的函数,如果暴露于任何未经验证的输入,都会成为严重的安全问题。

可以通过转义特殊字符来绕过这些问题,但转义很棘手,很难测试您是否涵盖了每个字符。特殊字符也具有 平台特定性,使得获得良好的测试覆盖率更加困难。正确执行所有这些操作的难度通常会超过 duct_sh crate 本身提供的任何便利。

因此,除了上述的可移植性相关考虑之外,大多数用于生产的程序应首选 duct 而不是 duct_sh。由于 duct 完全避免调用 shell,因此通常不会受到 shell 注入的攻击。

依赖关系

~0–7MB
~40K SLoC