< 返回版块

xiaoyureed 发表于 2020-08-13 16:17

Tags:shell, command

我在尝试编写一个命令行程序, 代码是这样:

fn main() {
    // a 是根目录下的一个文本文件, 已经写入了一行文本
    if let Ok(output) = Command::new("tail").args(&["-f", "a"]).output() {
        let s =  if output.status.success() {String::from_utf8_lossy(&output.stdout)} else {String::from_utf8_lossy(&output.stderr)};
        println!("{}", s);
    }
}

执行后 , 程序没有任何输出, 尝试修改 文件 a, 程序还是没有输出; 然后我修改成下面的代码:

fn main() {
    let child = Command::new("tail").args(&["-f", "a"]).stdin(Stdio::piped()).stdout(Stdio::piped()).spawn().expect("failed tail command");
    let mut s = String::new();
    child.stdout.expect("error of stdout").read_to_string(&mut s).expect("error of read all");
    println!("{}", s);
}

执行后, 没有输出, 修改 a 后, 打印出 tail: a: file truncated

执行有持续输出的shell命令应该怎么写呢 有哪位兄弟懂得嘛?

评论区

写评论
Neutron3529 2020-08-15 17:08

...and append them to the provided buffer... 你忘记把line清空了 试试在结尾来一句line.drain(..);就好

--
👇
xiaoyureed: 我改成这样, 又碰到新问题, 得向您再请教下:

fn main() {
    let child = Command::new("tail")
        .args(&["-f", "a"])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("failed tail command");

    let stdout = child.stdout.expect("error of stdout");
    let mut buf_reader = BufReader::new(stdout);
    let mut line = String::new();
    loop {
        buf_reader.read_line(&mut line).expect("error of read line");
        write!(std::io::stdout(), "{}", &line.as_str()).expect("error of writeln");
    }
}

修改文件 a新加一行, 不仅新行打印了, 前面所有的行都重复打印了, 这是为啥呢 😢?

--
👇
Neutron3529: 一样的

因为程序还没停止,读stdout的代码总觉得还能读到什么于是会一直等待程序出结果。

显示的file truncated可能是stderr而非stdout


👇
xiaoyureed: 第一段程序我理解了, 但是第二段为啥不行呢, child 是运行中的子进程, rust 程序不必等到子进程结束就能拿到输出.

整懵了.


👇
Neutron3529: 你或许应该用async

tail -f不会自动停止

.output()默认会等待程序停止

在你执行.output()的时候,程序只会默默等待tail -f a结束,而事实上这个程序永远都不会结束

于是你什么都得不到。

曾经我想写一个ggzero在linux下的Terminal UI界面,用linux玩ggzero引擎

现在……TUI界面负责输出命令,我负责把命令粘贴到ggzero,之后把ggzero的命令粘贴回TUI

……

作者 xiaoyureed 2020-08-15 10:54

我改成这样, 又碰到新问题, 得向您再请教下:

fn main() {
    let child = Command::new("tail")
        .args(&["-f", "a"])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("failed tail command");

    let stdout = child.stdout.expect("error of stdout");
    let mut buf_reader = BufReader::new(stdout);
    let mut line = String::new();
    loop {
        buf_reader.read_line(&mut line).expect("error of read line");
        write!(std::io::stdout(), "{}", &line.as_str()).expect("error of writeln");
    }
}

修改文件 a新加一行, 不仅新行打印了, 前面所有的行都重复打印了, 这是为啥呢 😢?

--
👇
Neutron3529: 一样的

因为程序还没停止,读stdout的代码总觉得还能读到什么于是会一直等待程序出结果。

显示的file truncated可能是stderr而非stdout


👇
xiaoyureed: 第一段程序我理解了, 但是第二段为啥不行呢, child 是运行中的子进程, rust 程序不必等到子进程结束就能拿到输出.

整懵了.


👇
Neutron3529: 你或许应该用async

tail -f不会自动停止

.output()默认会等待程序停止

在你执行.output()的时候,程序只会默默等待tail -f a结束,而事实上这个程序永远都不会结束

于是你什么都得不到。

曾经我想写一个ggzero在linux下的Terminal UI界面,用linux玩ggzero引擎

现在……TUI界面负责输出命令,我负责把命令粘贴到ggzero,之后把ggzero的命令粘贴回TUI

……

Neutron3529 2020-08-14 02:45

一样的

因为程序还没停止,读stdout的代码总觉得还能读到什么于是会一直等待程序出结果。

显示的file truncated可能是stderr而非stdout


👇
xiaoyureed: 第一段程序我理解了, 但是第二段为啥不行呢, child 是运行中的子进程, rust 程序不必等到子进程结束就能拿到输出.

整懵了.


👇
Neutron3529: 你或许应该用async

tail -f不会自动停止

.output()默认会等待程序停止

在你执行.output()的时候,程序只会默默等待tail -f a结束,而事实上这个程序永远都不会结束

于是你什么都得不到。

曾经我想写一个ggzero在linux下的Terminal UI界面,用linux玩ggzero引擎

现在……TUI界面负责输出命令,我负责把命令粘贴到ggzero,之后把ggzero的命令粘贴回TUI

……

作者 xiaoyureed 2020-08-13 22:26

第一段程序我理解了, 但是第二段为啥不行呢, child 是运行中的子进程, rust 程序不必等到子进程结束就能拿到输出.

整懵了.

--
👇
Neutron3529: 你或许应该用async

tail -f不会自动停止

.output()默认会等待程序停止

在你执行.output()的时候,程序只会默默等待tail -f a结束,而事实上这个程序永远都不会结束

于是你什么都得不到。

曾经我想写一个ggzero在linux下的Terminal UI界面,用linux玩ggzero引擎

现在……TUI界面负责输出命令,我负责把命令粘贴到ggzero,之后把ggzero的命令粘贴回TUI

……

Neutron3529 2020-08-13 18:29

你或许应该用async

tail -f不会自动停止

.output()默认会等待程序停止

在你执行.output()的时候,程序只会默默等待tail -f a结束,而事实上这个程序永远都不会结束

于是你什么都得不到。

曾经我想写一个ggzero在linux下的Terminal UI界面,用linux玩ggzero引擎

现在……TUI界面负责输出命令,我负责把命令粘贴到ggzero,之后把ggzero的命令粘贴回TUI

……

1 共 5 条评论, 1 页