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 在 命令行界面 中
628 每月下载量
在 8 crates 中使用
115KB
1.5K SLoC
duct_sh
是构建由 shell 字符串组成的命令的 duct
crate 的便利包装器。Duct 通常直接执行命令,而无需通过 shell。这可能是首选的,因为它避免了棘手的空白问题以及 shell 注入漏洞。然而,有时你需要访问更多奇特的 shell 功能(例如,shell 内置函数如 source
和 exec
,或使用 <()
的进程替换),而有时你只能运行一些 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