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

跨SSH会话运行Expect脚本无法终止远程Java进程问题求助

问题原因分析与解决方案

核心问题

本地运行脚本正常,但远程ssh调用失败的根本原因是终端环境差异:

  • 在server2本地运行脚本时,Expect处于交互式终端环境,PowerShell启动后会输出预期的PS*> 提示符,脚本能正常匹配并执行后续命令。
  • 但从server1通过ssh user@server2 './java_kill'调用时,server2上的Expect运行在非交互式无终端(non-interactive/non-tty)环境下,PowerShell启动后的输出行为发生了变化——它不会输出PS*> 提示符,甚至可能没有任何标准输出,导致脚本里的expect "PS*> "匹配超时,后续的终止命令Get-Process Java | Stop-Process被发送到了未就绪的会话中,根本没被PowerShell接收执行。

从你提供的日志也能验证这一点:发送powershell.exe\r后,Expect的缓冲区是空的(does "" match glob pattern "PS*> "? no),说明没有收到PowerShell的预期输出,超时后直接发送了终止命令,自然无法生效。

可行解决方案

方案1:强制分配伪终端

从server1执行ssh命令时,添加-t参数强制为远程会话分配伪终端,让server2上的Expect运行在交互式环境下:

ssh -t user@server2 './java_kill'

这样PowerShell启动后会输出正常的PS*> 提示符,脚本就能按预期匹配执行。

方案2:简化脚本,直接远程执行命令

放弃交互式PowerShell会话,通过ssh直接传递PowerShell命令,彻底避免提示符匹配问题:
修改后的java_kill脚本:

#!/usr/bin/expect -f

spawn ssh -l user server3 "powershell.exe -Command \"Get-Process Java | Stop-Process\""
expect "*passphrase*"
send "passphrase\r"
expect "*assword*"
send "password\r"
expect eof

这种方式更高效,也避免了终端环境带来的不确定性。

方案3:优化匹配逻辑(调试用)

如果必须保留交互式会话,可以先开启Expect的调试日志,查看PowerShell实际输出内容,再调整匹配规则:
在脚本开头添加exp_internal 1,这样会输出所有输入输出细节,帮助你确定PowerShell实际的输出内容,再修改expect的匹配模式(比如用更通用的*或者实际输出的提示符)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 11:23:28