我试图理解为什么在使用 bash -c
表达式运行命令时没有得到 Err()
结果。
这是一个示例和下面的输出。我希望 out2
和 out3
是一个 Err()
但是 out3
是一个状态为失败的 Ok()
。
我正在使用 bash -c
从给定字符串执行命令,这很简单。
可以使用 bash -c
语法得到 Err()
结果吗?
#![allow(unused)]
use std::process::{Command, Output};
fn main() {
let out1 = Command::new("bash").arg("-c").arg("ls").output();
println!("out1: {:?}", out1);
let out2 = Command::new("wrongcommand").arg("-c").arg("ls").output();
println!("out2: {:?}", out2);
let out3 = Command::new("bash").arg("-c").arg("wrongcommand").output();
println!("out3: {:?}", out3);
}
输出:
out1: Ok(Output { status: ExitStatus(ExitStatus(0)), stdout: "Cargo.lock\nCargo.toml\ncrate-information.json\nsrc\ntarget\n", stderr: "" })
out2: Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })
out3: Ok(Output { status: ExitStatus(ExitStatus(32512)), stdout: "", stderr: "bash: wrongcommand: command not found\n" })
我从命令行尝试过
$ bash -c wrongcommand
和
$ wrongcommand
并且都返回相同的退出代码 (127)。这就是为什么我预计 Command 会以同样的方式失败。
最佳答案
这很容易解释。关注list of error codes
out1
是 Ok
原因很明显
out2
是Err
类型,因为Command
直接找进程,找不到,返回ENOENT
(代码 2)。此错误发生在 rust 中,实际上没有执行任何操作。
out3
是 Ok
因为 Command
运行的进程是 bash
,它返回了它的状态。在这种情况下,它不会找到该命令,因此通过 bash 状态,它会返回 127。但是,这并不容易,因为 ExitStatus
中包含额外的信息层.在unix上,当一个进程失败时,它实际上返回一个16bit/32bit的整数(基于platform/libc/etc),一分为二:
- 最高位是触发返回的信号
- 最低8位为进程返回状态
毫不奇怪,如果我们向右移动 32512 个 8 位(它是一个 u16
),我们得到... 127!
要点很简单:
Err
definitely 表示进程没有运行Ok
表示主进程已运行,但您需要检查ExitStatus::success()
以确认它确实运行了(即退出状态为 0)
你可以像这样恢复它:
Command::new("bash").arg("-c").arg("wrongcommand").output().and_then(|r| match r.status.success() {
true => Ok(r),
false => Err(io::Error::new(io::ErrorKind::InvalidData, "Process error"))
});
您可以在 playground 上玩这个. success()
是子进程成功的可靠指标;它所做的只是检查退出状态的最低有效 8 位是否非零。
显然,如果进程在成功时返回非零值,这将无济于事,但那是另一个问题。
关于bash - std::process:Command 在使用 'bash -c' 时不返回 Err() 结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57956747/