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

使用Expect脚本通过cat命令远程复制文件失败求助

问题原因

你的Expect脚本失效的核心问题是:

  • 重定向> /tmp/localpassfile直接把ssh的标准输出(stdout)写入本地文件,但ssh的密码提示是输出到**标准错误流(stderr)**的
  • Expect默认只监听spawn进程的stdout,因此无法捕获到密码提示,脚本会卡在expect "assword"步骤
  • 加上-q参数会进一步抑制ssh的提示输出,加剧了这个问题

而直接在Shell执行命令时,终端会同时显示stdout和stderr内容,你能看到密码提示并输入,ssh的stdout也能正常写入文件,所以可以正常工作。

解决方法

方法一:用Shell包裹命令,合并stderr到stdout

通过sh -c包裹命令,把stderr合并到stdout,让Expect能捕获到密码提示,同时保证远程文件内容能写入本地:

#!/usr/bin/expect

set timeout -1

spawn sh -c "/usr/bin/ssh root@testserver cat /tmp/passfile > /tmp/localpassfile 2>&1"

expect "assword:"
send "welcome1\r"
expect eof

方法二:捕获输出后过滤写入文件

不提前做重定向,先让Expect捕获所有输出,过滤掉密码提示等无关内容后写入本地文件:

#!/usr/bin/expect

set timeout -1
set local_file "/tmp/localpassfile"

spawn /usr/bin/ssh root@testserver cat /tmp/passfile

expect {
    "assword:" {
        send "welcome1\r"
        exp_continue
    }
    eof {}
}

# 过滤掉密码提示和输入的密码,只保留远程文件内容
set output [string map {"assword:" "" "welcome1" ""} $expect_out(buffer)]
set output [string trim $output]

# 写入本地文件
set fp [open $local_file w]
puts $fp $output
close $fp

方法三:强制分配伪终端

给ssh加上-tt参数强制分配伪终端,确保密码提示能被输出:

#!/usr/bin/expect

set timeout -1

spawn /usr/bin/ssh -tt root@testserver cat /tmp/passfile > /tmp/localpassfile

expect "assword:"
send "welcome1\r"
expect eof

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 19:05:33