You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Rust中向less管道输出时覆盖Shell提示符?

问题描述

运行以下Rust程序时,管道到less的输出会覆盖Shell提示符,需要多次按回车才能恢复正常提示符:

use std::process::{Command, Stdio};
use std::io::{self, Write};

fn main() -> io::Result<()> {
    let mut child = Command::new("less")
        .args(["--quit-if-one-screen"])
        .stdin(Stdio::piped())
        .spawn()?;
    let child_stdin = child.stdin.as_mut().unwrap();
    child_stdin.write_all(b"Hello, world!\n")?;
    drop(child_stdin);

    Ok(())
}

异常输出:

% cargo run --bin pager
   Compiling single v0.1.0 (/Users/robenkleene/Developer/Scratch/Rust/single)
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s
     Running `target/debug/pager`
Hello, world!

期望输出:

% cargo run --bin pager
   Compiling single v0.1.0 (/Users/robenkleene/Developer/Scratch/Rust/single)
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/pager`
Hello, world!
%
解决方案

问题核心是父进程没有等待less子进程完全退出就提前结束,导致Shell过早输出提示符,被less的终端状态恢复操作覆盖。只需在释放子进程标准输入后,调用child.wait()?阻塞等待子进程终止即可。

修改后的代码:

use std::process::{Command, Stdio};
use std::io::{self, Write};

fn main() -> io::Result<()> {
    let mut child = Command::new("less")
        .args(["--quit-if-one-screen"])
        .stdin(Stdio::piped())
        .spawn()?;
    let child_stdin = child.stdin.as_mut().unwrap();
    child_stdin.write_all(b"Hello, world!\n")?;
    drop(child_stdin);
    
    // 等待less进程完全退出,确保终端状态恢复正常
    child.wait()?;

    Ok(())
}

说明:

  • spawn()仅启动子进程,父进程会继续执行后续代码并退出,此时Shell会立刻显示提示符,但less可能仍在处理终端状态恢复,导致输出覆盖提示符。
  • child.wait()会阻塞父进程,直到less完全终止并恢复终端状态后,父进程才退出,Shell就能正确显示提示符。

内容的提问来源于stack exchange,提问作者robenkleene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 05:58:10