简体   繁体   English

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

[英]std::process:Command not returning Err() result when using 'bash -c'

I'm trying to understand why I'm not getting an Err() result when using bash -c expression to run a command. 我试图理解为什么在使用bash -c表达式运行命令时为什么没有得到Err()结果。

Here is an example and the output below. 这是一个示例,下面是输出。 I expect out2 and out3 to be an Err() but out3 is an Ok() with the failed status. 我期望out2out3Err()但是out3是具有失败状态的Ok()

I'm using bash -c to execute a command from a given string, which is easy. 我正在使用bash -c从给定的字符串执行命令,这很容易。

It's possible to get an Err() result using bash -c syntax? 可以使用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);
}

Output: 输出:

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" })

I tried from command line and 我从命令行尝试过

$ bash -c wrongcommand

and

$ wrongcommand

and both return the same exit code (127). 两者都返回相同的退出代码(127)。 That's why I expected that Command failed in the same way. 这就是为什么我期望Command以相同的方式失败的原因。

That can be explained pretty easily. 这很容易解释。 Follow along on the list of error codes 遵循错误代码列表

out1 is Ok for obvious reasons out1Ok原因很明显

out2 is an Err type because Command directly looked for the process, could not find it, and returned ENOENT (code 2). out2是一种Err类型,因为Command直接查找该进程,找不到该进程,并返回ENOENT (代码2)。 This error happened within rust, nothing was actually executed. 此错误发生锈中,实际上未执行任何操作。

out3 is Ok because the process that Command ran is bash , and it returned its status. out3Ok ,因为过程Commandbash ,并返回其状态。 In this case, it wouldn't have found the command, so by bash statuses, it'll have returned 127. However, it's not that easy, because there is an additional layer of information contained in ExitStatus . 在这种情况下,它找不到命令,因此按bash状态返回127。但是,这并不容易,因为ExitStatus包含一层附加信息。 On unix, when a process fails, it actually returns a 16bit/32bit integer (based on platform/libc/etc), separated in two: 在unix上,当进程失败时,它实际上返回一个16位/ 32位整数(基于platform / libc / etc),分为两个:

  • The highest bits are what signal triggered the return 最高位是触发返回的信号
  • The lowest 8 bits are the return status of the process 最低的8位是进程的返回状态

And, to no surprise, if we shift 32512 8 bits to the right (it was an u16 ), we get... 127! 而且,毫不奇怪,如果我们将32512 8位右移(这是一个u16 ),我们得到... 127!

The takeaway is simple: 要点很简单:

  • Err definitely means the process didn't run Err 肯定表示该流程未运行
  • Ok means the main process ran, but you'll need to check ExitStatus::success() to confirm that it actually did (ie 0 as exit status) Ok意味着主进程已经运行,但是您需要检查ExitStatus::success()以确认它确实已经完成(例如,退出状态为0)

You could recover it like so: 您可以这样恢复它:

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"))
});

You can play with this on the playground . 您可以在操场上玩。 success() is a decently reliable indicator of child process success; success()是子进程成功的可靠指标; all it does is check if the least significant 8 bits of the exit status is non-zero. 它所做的只是检查退出状态的最低有效8位是否为非零。

Obviously, this does not help if a process returns non-zero on success, but that's a different problem. 显然,如果进程成功返回非零值,则无济于事,但这是另一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM