我有一个问题,以下功能
remote.send("show run int vlan 1\\n")
不起作用。代码如下。它能够读取文件、创建新文件以及写入和保存文件。然而,输出仅包含开关名称,没有其他内容,有时它会显示开关名称和命令的一个或两个字符。输出如下
switch test1
IP address 1.1.1.51
test1_2023-02-23
Successfully log in to test1
test1#s
switch test2
IP address 1.1.1.50
Test2_2023-02-23
Successfully log in to test2
test2#
刚开始学习语言,我不确定问题是什么。预先感谢您。
myfile = open('c:\znet\device-list.txt','r')
count = 0
while True:
count = count + 1
line = myfile.readline()
if not line:break
else:
x = line.strip()
y,z =x.split(",",1)
print ("switch ",y)
print ("IP address ",z)
backupdate = str(date.today())
filename = y + "_" + backupdate
print (filename)
host = z
user = 'cisco'
password = 'cisco'
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
client.connect(hostname=host, username=user, password=password)
print ("Successfully log in to", y)
remote = client.invoke_shell()
remote.send("show run int vlan 1\n")
output = remote.recv(1048576)
print (output.decode('ascii'))
with open("{}.txt".format(filename),"w") as f:
print (output.decode('ascii'),file=f)
我希望在终端和创建的文件中看到 vlan 1 (
show run int vlan 1
) 的配置。
Martin 是正确的,我已经编写了一些代码,当设备将数据发送回 SSH 通道时,这些代码将有助于检查和收集数据。代码有注释,应该是有意义的。
import paramiko, time
HOST = "x.x.x.x"
PORT = 22
USERNAME = "xxx"
PASSWORD = "xxx"
def ClearBuffer(connection: paramiko.Channel, sleeptime: float, lookfor: str):
# This will get rid of all the login information, like banners etc.
buffer: str = ""
timer: float = 0.0
error: int = 0
errorDescription: str = ""
while not buffer.endswith(lookfor):
if timer > 10.0:
error: int = 1
errorDescription: str = "Reached command timeout"
break
if connection.recv_ready():
buffer += connection.recv(65535).decode()
time.sleep(sleeptime)
timer += sleeptime
return(buffer) if error != 1 else errorDescription
def ExecuteSingleCommand(connection: paramiko.Channel, command: str, sleeptime: float, lookfor: str):
buffer: str = ""
timer: float = 0.0
error: int = 0
errorDescription: str = ""
connection.send(f"{command}\n") # Send command to device and press enter (\n)
while not buffer.endswith(lookfor): # Continuously look for lookfor, which in this case is #
if timer > 30.0: # Set a general timer in order to stop execution after 30 seconds
error = 1
errorDescription = "Reached command timeout"
break
if connection.recv_ready(): # Check if channel has data
buffer += connection.recv(65535).decode() # Save channel data
if "--More--" in buffer: # Specific for Cisco devices, if 'terminal length 0' is not entered, channel waits for key press
errorDescription = "Paging not disabled"
break
time.sleep(sleeptime) # wait for sleep time seconds
timer += sleeptime
return(buffer.strip(command).strip(lookfor).strip()) if error != 1 else errorDescription
def ExecuteCommand(cmdlist: list, sleeptime: float=0.1, lookfor: str="#"):
# sleeptime = time to wait before checking for data
# lookfor = the character to look for in the SSH shell to indicate the command was executed
results: list = []
error: int = 0
with paramiko.SSHClient() as ssh: # Connect to devices using a context manager, which will automatically close connections
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, PORT, USERNAME, PASSWORD, timeout=300, banner_timeout=240, look_for_keys=False) # Connect to device
connection: paramiko.Channel = ssh.invoke_shell() # Invoke shell for interactive commands
invoke = ClearBuffer(connection, sleeptime, lookfor) # Clear the current channel buffer for login information
if "Reached command timeout" not in invoke: # Check that clear buffer did not timeout, e.g. it couldn't find lookfor in the buffer
for cmd in cmdlist: # Iterate every command
cmdResult = ExecuteSingleCommand(connection, cmd, sleeptime, lookfor) # Execute every single command
if "Reached command timeout" not in cmdResult: # Check that connection didn't time out
results.append(cmdResult) # Append results
else:
error = 1
else:
error = 1
return(results) if error != 1 else None
print(ExecuteCommand(["terminal length 0", "sh run"]))
测试结果:
['xxx-xx-3560CG-01', 'Building configuration...\r\n\r\nCurrent configuration : 5893 bytes\r\n!\r\n! Last configuration change at 09:30:59 CET Mon Jan 17 2022 by...TRUNCATED]
您应该能够优化代码并轻松地自己添加其他功能。
recv
不会返回整个输出。这不可以。您正在使用 shell (invoke_shell
)。 shell 是一个永无休止的间歇性数据流。唯一的结局是注销。也没有任何信号表明特定命令的完整输出已结束。 recv
返回您调用它时可用的任何数据。如果你想要完整的输出,你需要反复调用recv
,直到得到全部。这是原因之一,为什么一般来说,您不应该使用
invoke_shell
进行命令自动化。