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

在Rust中如何获取process::Command的完整输出并显示到终端?

问题:Rust中执行scp命令无法显示终端输出及自动填充密码

我正尝试用Rust重构自己的bash脚本(Rust支持哈希与更多自定义功能),但无法将process::Command执行scp命令的输出显示到终端,尝试多种stdout管道方式后仍无进展。我希望在命令行中看到如下scp输出(含密码提示与传输进度)并实现自动填充密码(已知ssh密钥的存在):

user@server's password:
ibits.c                                                                  100% 1137   271.2KB/s   00:00

我的auto_scp函数代码:

fn auto_scp(flags: FlagOptions, f_path: String) {
    let info = open_config();
    let mut args: Vec<String> = vec![];
    if flags.is_folder {
        args.push(String::from("-r"))
    }
    if flags.d_load {
        let path = info.rmt_hst+":"+&f_path;
        // println!("{}",path);
        args.push(path);
        args.push(info.ddest);
    } else {
        let path = info.rmt_hst+":"+&info.udest;
        // println!("{}",path);
        args.push(f_path);
        args.push(path);
    }
    let mut com = process::Command::new("/bin/scp")
                                  .args(args)
                                  .stdout(process::Stdio::piped())
                                  .output()
                                  .expect("stuff");
    // io::stdout().write_all(b"hello world\n");
                                  // .expect("Could not output");
    // let stdout = String::from_utf8(com.stdout).unwrap();
    println!("stdout: {}", String::from_utf8(&com.stdout));
    // io::stdout().write_all(&outc.stdout).unwrap();
    println!("{}", stdout);
    return;
}
解决方案

一、让scp输出直接显示到终端

你的代码用.stdout(process::Stdio::piped())和.output()会把scp的输出捕获到内存,而非直接转发到终端。要实时看到输出,需让子进程继承当前进程的标准输入、输出和错误流,无需手动捕获:

修改命令执行部分:

process::Command::new("/bin/scp")
    .args(args)
    .status()
    .expect("scp command failed");
  • .status()会等待命令执行完成并返回退出状态,不会捕获输出
  • 移除.stdout(process::Stdio::piped()),scp的stdout、stderr会直接关联到当前终端,就能看到密码提示和传输进度

二、自动处理密码(基于SSH密钥)

既然确认SSH密钥存在,优先通过密钥认证跳过密码输入:

  1. 检查本地私钥权限为600(执行chmod 600 ~/.ssh/id_rsa)
  2. 确认服务器~/.ssh/authorized_keys已添加你的公钥,文件权限600、目录权限700
  3. 如果密钥路径非默认~/.ssh/id_rsa,在scp参数中添加-i指定路径,比如:
    args.push("-i".to_string());
    args.push("/path/to/your/private/key".to_string());
    

若必须用密码填充(密钥不可用场景),可借助sshpass工具,修改命令为:

process::Command::new("sshpass")
    .args(["-p", "your_password", "/bin/scp"])
    .args(args) // 原scp参数
    .status()
    .expect("sshpass+scp command failed");

注意:明文写密码有安全风险,优先用SSH密钥认证。

三、完整修改后的函数示例

fn auto_scp(flags: FlagOptions, f_path: String) {
    let info = open_config();
    let mut args: Vec<String> = vec![];
    // 如需指定密钥路径,取消下方注释
    // args.push("-i".to_string());
    // args.push("/path/to/your/private/key".to_string());
    
    if flags.is_folder {
        args.push(String::from("-r"));
    }
    
    if flags.d_load {
        let path = format!("{}:{}", info.rmt_hst, f_path);
        args.push(path);
        args.push(info.ddest);
    } else {
        let path = format!("{}:{}", info.rmt_hst, info.udest);
        args.push(f_path);
        args.push(path);
    }
    
    process::Command::new("/bin/scp")
        .args(args)
        .status()
        .expect("Failed to execute scp command");
}

说明:用format!代替字符串拼接更符合Rust习惯,可避免所有权问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 11:50:23