paramiko抛出'No existing session'异常时标准输入流挂起问题咨询
问题根因分析
- 未消费子进程的stderr流是核心诱因。你当前的Java代码仅读取了Python进程的标准输出(stdout),完全没有处理标准错误流(stderr)。Paramiko抛出的
Paramiko: 'No existing session' error: try increasing 'conn_timeout' to 10 seconds or larger.报错是底层依赖库直接输出到stderr的,你的Python业务代码没有捕获这部分输出做重定向,也没有其他逻辑消费stderr内容。当stderr的缓冲区被操作系统写满后,Python进程会被直接阻塞暂停执行,既不会输出新的stdout内容,也不会退出,导致Java侧的readLine()方法一直等待新的行输出,永远无法返回,触发挂起。 - Java读取逻辑存在设计漏洞。你判断进程是否存活的分支放在了
readLine()调用之后,只要Python进程没有主动关闭stdout、也没有新的stdout输出,readLine()会一直处于阻塞状态,根本不会执行到pr.isAlive()的判断逻辑,就算Python进程已经被缓冲区阻塞挂住,Java侧也无法感知。 - "SSH protocol banner"异常不会触发挂起的原因是该异常被你的Python代码显式捕获后,通过
save_log()输出到了stdout,没有内容写入stderr,不会触发stderr缓冲区满的阻塞问题,Python进程可以正常执行重试逻辑,stdout会持续输出内容,Java的读取逻辑不会被阻塞。
修复方案
- Java侧启动子进程后,必须同时消费stdout和stderr两个流,可以启动两个独立线程分别读取两个流,避免任意一个缓冲区被填满导致子进程阻塞。
- 可以直接调整Python启动命令,将stderr重定向合并到stdout,同时禁用Python的输出缓冲:将启动命令修改为
python -u py/grabber/backdoor.py " + args + " 2>&1,其中-u参数强制Python的stdout/stderr输出不做缓冲,2>&1将stderr合并到stdout,Java仅读取一个流即可避免该问题。 - 调整Java读取逻辑,给流读取操作增加超时判断,避免无限等待。
内容的提问来源于stack exchange,提问作者David Pace
相关产品推荐
相关产品推荐

