У меня возникли проблемы с управлением моим TP-Link TL-SG2218. В прошивку поставщика встроен SSH CLI. И использование стандартной консоли Linux-консоли SSH-клиента CLI работает действительно ИДЕАЛЬНО.
Вот пример того, что я делаю (я включаю порт №10):
Код: Выделить всё
unit-1@unit1:~$ ssh admin@192.168.21.79
admin@192.168.21.79's password:
TL-SG3428>enable
TL-SG3428#configure
TL-SG3428(config)#interface gigabitEthernet 1/0/10
TL-SG3428(config-if)#no shutdown
TL-SG3428(config-if)#exit
TL-SG3428(config)#exit
TL-SG3428#copy running-config startup-config
Start to save user config as the Next Startup Config file......
Saving user config OK!
TL-SG3428#exit
TL-SG3428>exit
Connection to 192.168.21.79 closed.
unit-1@unit1:~$
И мне нужно сделать то же самое, но из кода Python
Что я пробовал:
Решение 1
Использовать стандартную библиотеку SSH (paramiko)Код: Выделить всё
ssh = paramiko.SSHClient()
ssh.connect(ip, username=login, password=password, auth_timeout=20,
channel_timeout=20)
ssh.exec_command(command)
Решение 2
Использование paramiko, но реализация интерактивного оболочка (использовать канал)Код: Выделить всё
ssh = paramiko.SSHClient()
ssh.connect(ip, username=login, password=password, auth_timeout=20,
channel_timeout=20)
channel = ssh.invoke_shell()
self.channel.send(command.encode("UTF-8"))
buff = ''
while "#" not in buff and ">" not in buff:
resp = self.channel.recv(4096)
buff += resp.decode("UTF-8")
print(buff)
print(buff)
Решение 3 (Netmiko)
Я нашел эту библиотеку Python: netmikoИспользуя этот код, я наконец смог правильно выполнять команды
Код: Выделить всё
from netmiko import ConnectHandler
switch = {
'device_type': 'tplink_jetstream',
'host': ip,
'username': login,
'password': password
}
net_connect = ConnectHandler(**switch)
net_connect.send_command(command)
И еще в 50% случаев я всегда получить это исключение (абсолютно случайно, после случайной команды)
Код: Выделить всё
[EXECUTING]enable
Already in admin level.
[EXECUTING]configure
TL-SG3428#configure
[EXECUTING]interface gigabitEthernet 1/0/10
INFO: 172.22.0.1:55758 - "POST /disable_switch HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/fastapi/applications.py", line 1054, in __call__
await super().__call__(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/applications.py", line 123, in __call__
await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/middleware/errors.py", line 186, in __call__
raise exc
File "/usr/local/lib/python3.11/site-packages/starlette/middleware/errors.py", line 164, in __call__
await self.app(scope, receive, _send)
File "/usr/local/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 65, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
raise exc
File "/usr/local/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
await app(scope, receive, sender)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 756, in __call__
await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 776, in app
await route.handle(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 297, in handle
await self.app(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 77, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
raise exc
File "/usr/local/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
await app(scope, receive, sender)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 72, in app
response = await func(request)
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/contextlib.py", line 222, in __aexit__
await self.gen.athrow(typ, value, traceback)
File "/usr/local/lib/python3.11/site-packages/fastapi/concurrency.py", line 35, in contextmanager_in_threadpool
raise e
netmiko.exceptions.ReadTimeout:
Pattern not detected: 'TL\\-SG3428\\(config\\)\\#' in output.
Things you might try to fix this:
1. Explicitly set your pattern using the expect_string argument.
2. Increase the read_timeout to a larger value.
You can also look at the Netmiko session_log or debug log for more information.
Что вы можете посоветовать?
Я думаешь о двух способах:
- Использовать консольный ssh-клиент Linux из Python, что-то вроде Popen или около того, и общаться с ним?
- Может быть, лучше настроить шаблон «expect_string» в netmiko? (потому что в принципе это работает, но не всегда)
- Может быть что-то еще? Мне просто нужен простой способ запустить команду CLI и получить результаты, как это происходит в SSH-клиенте Linux?
Подробнее здесь: https://stackoverflow.com/questions/789 ... rom-python