我希望能够使用Rust来生成一个子shell,然后重复传递任意命令并处理它们的输出。我在网上找到了很多示例,教我如何传递单个命令并接收其单个输出,但我似乎无法重复执行它们。
例如,下面的代码在注释后的行上挂起。(我想也许
显然,反复运行
最后,即使不能以这种方式使用子 shell,我仍然想学习如何重复/持续地将数据传输到和从运行其他任意命令的衍生进程中,因为我在 Rust 文档、教程或 Stack Overflow 中都找不到任何信息。
例如,下面的代码在注释后的行上挂起。(我想也许
read_to_string()
正在阻塞,直到它接收到子进程的标准输出,但如果是这样的话,我不明白为什么输出没有出现..)let mut child_shell = match Command::new("/bin/bash")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
{
Err(why) => panic!("couldn't spawn child_shell: {}", Error::description(&why)),
Ok(process) => process,
};
loop {
{
match child_shell.stdin.as_mut().unwrap().write("ls".as_bytes()) {
Err(why) => panic!(
"couldn't send command to child shell: {}",
Error::description(&why)
),
Ok(_) => println!("sent command to child shell"),
}
}
{
let mut s = String::new();
// ↓ hangs on this line ↓
match child_shell.stdout.as_mut().unwrap().read_to_string(&mut s) {
Err(why) => panic!("couldn't read bash stdout: {}", Error::description(&why)),
Ok(_) => print!("bash responded with:\n{}", s),
}
}
}
我是一名Rust初学者,我认为问题在于我对借用检查器/引用规则的理解有限。如果从代码中删除循环指令并将对std::process::Child
结构体内部的引用更改为不可变,则上述代码可以正常运行(对于单次迭代)。例如,从这个:
child_shell.stdin.as_mut().unwrap().write("ls".as_bytes())
转换为:
child_shell.stdin.unwrap().write("ls".as_bytes())
显然,反复运行
ls
不是我的终极目标,我知道我可以编写一个 shell 脚本,然后让 Rust 反复运行它 - 但是(除了学习更多关于 Rust 的知识之外!)这是我需要能够至少在原理上完成的事情,对于一个更复杂的项目来说尤其如此(如果可能与任何解决方案相关,我很乐意进一步介绍,但这可能远远超出了这个问题的范围!)最后,即使不能以这种方式使用子 shell,我仍然想学习如何重复/持续地将数据传输到和从运行其他任意命令的衍生进程中,因为我在 Rust 文档、教程或 Stack Overflow 中都找不到任何信息。
BufReader
读取,为什么在循环内尝试简单地调用child_out.lines().count()
或for l in child_out.lines()
会给我一个“使用已移动值:child_out”的错误?为什么我可以要求BufReader
提供一行,但不能要求它提供所有行?我是否在这里误解了迭代器的工作方式? - Johnself
参数如何工作。查看count
可以看到它通过值获取self
,这会消耗底层迭代器,与lines
相同。调用count
也没有意义,因为您必须读取 所有 进程输出才能获得计数,此时所有数据都已被丢弃。 - Shepmaster