尝试执行命令时使用Python 3 paramiko,EOFError进行SSH编程

时间:2016-06-28 13:26:18

标签: python ssh paramiko

stackoverflow的向导。我尝试使用paramiko从.txt文件读取命令到SSH。目前,它将从文件的第一行读取并执行它。当我到达第二行时,它会抛出一个EOFError并退出。我检查了第二个命令是否使它打印,然而它确实没有执行。我希望有人能够帮助我解决这个问题。这是我的代码:

from paramiko import client
import logging
import os

#Clear the screen before starting the script
os.system('cls')

# Prompting for the user input config file
filename = input('Input configuration filename, the file extension must be attached: ')

# Creating the LOG file for the execution of the config file
logFileName = "LOG" + filename[0:]
try:
    logging.basicConfig(filename= logFileName ,format='%(asctime)s %(message)s', level= logging.DEBUG)
    print ("The file was created!")
except IOError:
    print ("File failed to create")

logging.info("---------------------------------------------------------------------------")
logging.info("NEW CONFIGURATION LOG ENTRY")
logging.info("---------------------------------------------------------------------------")


# Class for creating an SSH client, logging in, letting us write out commands, and close the client.
class ssh:
    client = None
    def __init__(self, address, username, password):


        print ("Connecting to server...")
        logging.info('Connecting to server...')

        self.client = client.SSHClient()
        self.client.set_missing_host_key_policy(client.AutoAddPolicy())
        self.client.connect(address, username= username, password= password, look_for_keys= False)

        logging.info("Address: " + address)
        logging.info("Username: " + username)
        print ("Connection successful!")
        logging.info('Connection successful!')

    def sendCommand(self, command):
        if (self.client):
            stdin, stdout, stderr = self.client.exec_command(command)
            receiveData = b""
            while not stdout.channel.exit_status_ready():
                receiveData += stdout.channel.recv(1024)

            if stdout.channel.recv_ready():
                received = stdout.channel.recv(1024)
                while received:
                    receiveData += received
                    received = stdout.channel.recv(1024)

            if receiveData:
                print (str(receiveData, "utf8"))

            else:
                print ("stdout is empty")
        else:
            print ("Connection failed, check credentials and try again..")
            logging.warning('Connection failed, check credentials and try again..')

connection = ssh('0.0.0.0', 'test', 'test')
with open(filename) as f:
    for line in f:
        print(line)
        connection.sendCommand(line)

.txt文件的内容如下:

配置终端

接口Gi0 / 9

描述Test_Interface

非常感谢任何帮助,谢谢。

1 个答案:

答案 0 :(得分:1)

可能的错误。 sendCommand的当前实现可能无法接收输出(或完整输出)。

原因 exit_status_ready是一种阻止接收退出状态的非阻塞方式。输出的lastpart可能仍然没有被脚本读取。如果recvwhile,则需要在recv_ready之后致电True

另外,我不认为在while循环中检查recv_ready是个好主意。这是非阻塞方法。因为它while循环将无用地运行多次,只是浪费你的CPU能力。

此版本适用于我:

receiveData = b""
while not stdout.channel.exit_status_ready():
    receiveData += stdout.channel.recv( 2048 )

if stdout.channel.recv_ready():
    received = stdout.channel.recv( 2048 )
    while received: #received will be empty only when all data received
        receiveData += received
        received = stdout.channel.recv( 2048 )

if receiveData:
    print( str( receiveData, "utf8" ) )
else:
    print( "stdout is empty" )

另外我应该提一下,从输出构建字符串有更简单的方法。您可以使用stdinstdoutstderr类似文件的事实。

stderr这里有一个更简单的例子(读它也是个好主意):

data = ""
for line in stderr:
    #line in string already (probably will work only if locale is utf8)
    data += line 

if data:
    print( data ) 
else:
    print( "stderr is empty" )

更新: 如果你在一行上没有多个命令,那么

filename = input('Input configuration filename, the file extension must be attached: ')
# define ssh class here (i'll skip it to make it shorter)

connection = ssh('0.0.0.0', 'test', 'test')
with open(filename) as f:
   for line in f:
       connection.sendCommand( line )

如果每行有几个命令,只需将它们拆分为不同命令的数组。