首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当paramiko抛出“No existing session”异常时,标准输入流挂起

当paramiko抛出“No existing session”异常时,标准输入流挂起
EN

Stack Overflow用户
提问于 2021-07-02 01:59:14
回答 1查看 82关注 0票数 0

我正在使用java启动一个python脚本,方法如下:

代码语言:javascript
运行
复制
private String[] runScript(String args) {
        ArrayList<String> lines = new ArrayList<String>();
        try {
            String cmd = "python py/grabber/backdoor.py " + args;
            System.out.println(cmd);
            Runtime run = Runtime.getRuntime();
            Process pr = run.exec(cmd);
            InputStream stdout = pr.getInputStream();
            BufferedReader stdInput = new BufferedReader(new InputStreamReader(stdout, StandardCharsets.UTF_8));
            String line;
            System.out.println("Starting to read output:");
            while ((line = stdInput.readLine()) != null) {
                if(!pr.isAlive()) {
                    break;
                }
                System.out.println("" + line);
                lines.add(line);
            }
            stdInput.close();
        } catch (Exception e) {
            System.out.println("Exception in reading output" + e.toString());
        }
        return lines.toArray(new String[lines.size()]);
    }

python脚本开始为每个设备的新子线程上的设备列表执行以下方法:

代码语言:javascript
运行
复制
def run_command(device, retry):
    try:
        if(retry != 0):
            save_log('Retrying '+device['ip']+'...')
        SSHClient = netmiko.ssh_dispatcher("cisco_ios")
        ssh_connection = SSHClient(**device)

        ruckus = ("ruckus" in str(device['device_type']))

        output = ssh_connection.send_command('show run | inc hostname')
        if(not ruckus):
            output = output.split('\n')[0]
            hostname = output.split(' ')[1] + '-' + today
        else:
            hostname = output.split(' ')[1] + '-' + today

        msg = (''+device['ip']+':Retry Success! Hostname:'+hostname+'\n',''+device['ip']+':hostname: ' + hostname + '\n')[retry == 0]
        save_log(msg)
        return True
    except Exception as e:
        if("Authentication" in str(e)):
            if(config.exe_i):
                save_log('\nAuthentication failed! Consider resetting credentials\n')
                if(not config.using_gui):
                    val = input("Continue with list? [y]/[n]: ")
                    if("n" in val):
                        return False
                else:
                    return True
            else:
                msg = '\nSwitch: ' + device['ip'] + '\nLogin Failure'
                save_error(msg)
                return True
        elif("SSH protocol banner" in str(e) and retry <= 3):
            retry += 1
            save_log('\nSwitch: ' + device['ip'] + ' - SSH Banner.. Attempt: '+str(retry))
            return run_command(device, retry=retry)
        elif("conn_timeout" in str(e) and retry <= 3):
            retry += 1
            save_log('\nSwitch: ' + device['ip'] + ' - Connection Timeout.. Attempt: '+str(retry))
            return run_command(device, retry=retry)
        error = 'error @ switch: ' + device['ip'] + ' with error: \n' + str(e)
        save_error(error)
        return True

当python脚本获得此特定异常时,

代码语言:javascript
运行
复制
Paramiko: 'No existing session' error: try increasing 'conn_timeout' to 10 seconds or larger.

脚本将简单地重试连接并按预期正常进行,但是java程序开始在while循环处挂起,尽管python脚本成功地完成了执行。为什么当抛出此异常时,while循环中的标准输入流开始挂起?

其他信息:

1.)当从场景中取出线程时,如果抛出'no existing session‘异常,while循环仍然会挂起。

2.)导致重试ssh尝试的另一个常见异常"SSH protocol banner“不会导致while循环挂起。因此,我得出的结论是,问题不是在我的程序堆栈中处理异常本身的方式。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-03 08:13:05

问题出在Java段,解决方案是不仅要读取输入流,还要读取输出流,因为如果不清空这两个流,进程就会挂起。为了正确地做到这一点,每个流都需要在单独的线程上读取。ProcessBuilder是一个更好的选择,因为它允许您将输入流和输出流合并为一个,然后只需要主线程。

这篇堆栈文章引用了这个概念中更规范的问题:Java Process with Input/Output Stream

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68214928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档