bash - std::process:Command 在使用 'bash -c' 时不返回 Err() 结果

标签 bash command-line rust

我试图理解为什么在使用 bash -c 表达式运行命令时没有得到 Err() 结果。

这是一个示例和下面的输出。我希望 out2out3 是一个 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

out1Ok 原因很明显

out2Err类型,因为Command直接找进程,找不到,返回ENOENT(代码 2)。此错误发生在 rust 中,实际上没有执行任何操作。

out3Ok 因为 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/

相关文章:

bash - 有条件地运行脚本在 travis.yml 中不起作用,为什么?

bash - 获取错误 cp : cannot stat when trying to copy files from one folder to another

windows - 是否有任何 XSLT 处理命令行工具?

rust - 如何修改作为函数参数的切片?

rust - 如何使用 Serde 在反序列化期间转换字段?

rust - 为什么 Rust 的示例猜谜游戏允许具有不同返回类型的 match 语句?

linux - 运行脚本后不显示 shell 提示符

linux - 如何找到文件中特定行的字节位置

cocoa - 如何为 GUI Cocoa 应用程序创建命令行前端?

linux - korn shell 和环境变量