paramiko's ssh channel closed after executing one cmd - Python - python

I'm using Python's Paramiko to execute commands in a remove server. The code is much simple.
Here's my definition of the SSHConn class:
class SSHConn:
def __init__(self, hostname, user, pwd, filename=None):
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.client.connect(hostname, username=user, password=pwd,
key_filename=filename)
self.transport = self.client.get_transport()
self.channel = self.transport.open_session()
So I'm running the following code:
local_ssh = ssh.SSHConn(host, user, passwd)
cmds = ('foo', 'bar')
for cmd in cmds:
local_ssh.channel.exec_command(cmd)
self.log.info(local_ssh.channel.recv(1024))
However, when I execute the following code snipped I'm getting:
INFO:paramiko.transport:Connected (version 2.0, client OpenSSH_6.6.1p1)
INFO:paramiko.transport:Authentication (publickey) failed.
INFO:paramiko.transport:Authentication (password) successful!
INFO:paramiko.transport:Secsh channel 1 opened.
INFO:testsets.testcase:
ERROR:testsets.testcase:Channel is not open
Traceback (most recent call last):
File "/root/fds-src/source/test/integration-framework/testsets/testcases/test_100gb_volume.py", line 87, in runTest
local_ssh.channel.exec_command(cmd)
File "/usr/lib/python2.7/dist-packages/paramiko/channel.py", line 209, in exec_command
raise SSHException('Channel is not open')
SSHException: Channel is not open
ERROR:testsets.testcase:Test Case Test100GBVolume failed.
Traceback (most recent call last):
File "/root/fds-src/source/test/integration-framework/testsets/testcases/test_100gb_volume.py", line 87, in runTest
local_ssh.channel.exec_command(cmd)
File "/usr/lib/python2.7/dist-packages/paramiko/channel.py", line 209, in exec_command
raise SSHException('Channel is not open')
SSHException: Channel is not open
How can I keep the channel open?

The channel docs are very clear about this point. You need to open a new channel for each exec_command.
exec_command(*args, **kwds)
Execute a command on the server. If the server allows it, the channel will then be directly connected to the stdin, stdout, and stderr of the command being executed.
When the command finishes executing, the channel will be closed and can’t be reused. You must open a new channel if you wish to execute another command.
The SSHClient object has an exec_command method that does this for you.

Related

Paramiko "TypeError: 'NoneType' object is not callable" at the end of a script that execute command on the server

I'm writing a script to execute commands in an EC2 instance, and come back. For that, I'm using Paramiko. My script is like this:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('<hostname>', username='<username>', password='<password>')
print('connected')
stdin, stdout, stderr = ssh.exec_command("ls -lah")
ssh.close()
print('done')
The trace I'm getting is:
connected
done
Exception ignored in: <function BufferedFile.__del__ at 0x7fa5de814950>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/paramiko/file.py", line 66, in __del__
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/paramiko/channel.py", line 1392, in close
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/paramiko/channel.py", line 991, in shutdown_write
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/paramiko/channel.py", line 963, in shutdown
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/paramiko/channel.py", line 1246, in _send_eof
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/paramiko/message.py", line 232, in add_int
TypeError: 'NoneType' object is not callable
The command which I use to login is:
ssh -o PubkeyAuthentication=no -l <username> <hostname>
Can someone tell me what I'm doing wrong here?
You are not waiting for the command to complete before you close the SSH connection.
When Python garbage-collects the stdin, stdout and stderr, Paramiko crashes, as it does not expect the connection to be closed.
For a correct code, see Wait to finish command executed with Python Paramiko.
if ssh is not None:
ssh.close()
del client, stdin, stdout, stderr

Pyro4 [Errno -2]

I am trying out pyro4 connection between my PC and Raspberry Pi 4.
Code on my PC is:
# saved as server.py
import Pyro4, Pyro4.naming
import socket, threading
# Define an object that will be accessible over the network.
# This is where all your code should go...
#Pyro4.expose
class MessageServer(object):
def show_message(self, msg):
print("Message received: {}".format(msg))
# Start a Pyro nameserver and daemon (server process) that are accessible
# over the network. This has security risks; see
# https://pyro4.readthedocs.io/en/stable/security.html
hostname = socket.gethostname()
ns_thread = threading.Thread(
target=Pyro4.naming.startNSloop, kwargs={'host': hostname}
)
ns_thread.daemon = True # automatically exit when main program finishes
ns_thread.start()
main_daemon = Pyro4.Daemon(host=hostname)
# find the name server
ns = Pyro4.locateNS()
# register the message server as a Pyro object
main_daemon_uri = main_daemon.register(MessageServer)
# register a name for the object in the name server
ns.register("example.message", main_daemon_uri)
# start the event loop of the main_daemon to wait for calls
print("Message server ready.")
main_daemon.requestLoop()
And code on my Raspberry is:
import Pyro4
import sys
print("Message:")
msg=sys.stdin.readline().strip()
message_server = Pyro4.Proxy("PYRONAME:192.168.1.5")
message_server.show_message(msg)
Code on my PC doesn t show any errors, but when I try to send a message from raspberry i get this:
What s your message?
test
Traceback (most recent call last):
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 102, in getIpAddress
return getaddr(config.PREFER_IP_VERSION) if ipVersion is None else getaddr(ipVersion)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 94, in getaddr
ip = socket.getaddrinfo(hostname or socket.gethostname(), 80, family, socket.SOCK_STREAM, socket.SOL_TCP)[0][4][0]
File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 515, in connect_and_handshake
sslContext=sslContext)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 266, in createSocket
if getIpVersion(connect[0]) == 4:
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 68, in getIpVersion
address = getIpAddress(hostnameOrAddress)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 106, in getIpAddress
return getaddr(0)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 94, in getaddr
ip = socket.getaddrinfo(hostname or socket.gethostname(), 80, family, socket.SOCK_STREAM, socket.SOL_TCP)[0][4][0]
File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/pi/Desktop/client.py", line 10, in <module>
message_server.show_message(msg)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 275, in __getattr__
self._pyroGetMetadata()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 615, in _pyroGetMetadata
self.__pyroCreateConnection()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 588, in __pyroCreateConnection
uri = _resolve(self._pyroUri, self._pyroHmacKey)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 1915, in _resolve
return nameserver.lookup(uri.object)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 275, in __getattr__
self._pyroGetMetadata()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 615, in _pyroGetMetadata
self.__pyroCreateConnection()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 596, in __pyroCreateConnection
connect_and_handshake(conn)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 549, in connect_and_handshake
raise ce
Pyro4.errors.CommunicationError: cannot connect to ('JAKOB-PC', 9090): [Errno -2] Name or service not known
My PC has its firewall disabled, so there shouldn t be any problem with that. My local ip is 192.168.1.5.
I am using a headless Raspberry and write code on it with puTTY and VNC.
I have googled this error but couldn t find any answers. Any help would be appreciated.
I did this
#
# Server.py
#
from __future__ import print_function
import Pyro4
#Pyro4.expose
#Pyro4.behavior(instance_mode="single")
class Messenger(object):
# This is a constructor
def __init__(self):
pass
# This method will be called on the server
def send_message(self, name, message):
print("[{0}] {1}".format(name, message))
def main():
Pyro4.Daemon.serveSimple(
{
Messenger: "example.messenger"
},
ns=True)
if __name__ == "__main__":
main()
#
# Client.py
#
# This is the code that visits the warehouse.
import sys
import Pyro4
import Pyro4.util
sys.excepthook = Pyro4.util.excepthook
messenger = Pyro4.Proxy("PYRONAME:example.messenger#192.168.1.5")
messenger.send_message("Tim", "Hello!")
Then ran
python -m Pyro4.naming -n 192.168.1.5
python Server.py
python Client.py
In short I couldn't solve the problem with Pyro and (almost) no one helped so I decided to use 'websockets' instead.
You can read the documentation here but I'll explain it here anyway.
First of all you need two devices with network connection. You also have to run python 3.6.1 on both of them. After that you also need to install websockets if you don't have them already with pip install websockets or as I had to do it with pip3 install websockets.
Code below runs on the server and handles messages you send to it from client. Function 'hello' is a simple example of processing request and sending back a response. 'request' is the data server receives, that data must be bytes, string on iterable. Response is made by converting request to integer, squaring it and converting it back to string. This response is then sent back to client.
'start_server' defines the server, function that will define its behavior(hello), ip address on witch the server is running on(192.168.1.117) and port on witch it will receive requests(8765).
!/usr/bin/env python
import asyncio
import websockets
print("Running...")
async def hello(websocket, path):
request = await websocket.recv()
print("Request: " + request)
response = str(int(request)*int(request))
await websocket.send(response)
print("Response:" + response)
start_server = websockets.serve(hello, "192.168.1.117", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Next bit is code on the client. 'uri' is ip and port of the server. Function 'tellServ' asks you to input some data('tell' variable) and sends it to the server. After that it waits for reply and once it gets it it prints it out. In this case if I would input number "6" server would reply with "36". Function loop is in a while loop so I can send multiple numbers without having to restart the script.
#!/usr/bin/env python
import asyncio
import websockets
uri = "ws://192.168.1.117:8765"
async def tellServ():
async with websockets.connect(uri) as websocket:
tell = input("Podatek ki ga posles: ")
await websocket.send(tell)
reply = await websocket.recv()
print("Odgovor:")
print(reply)
while 1:
asyncio.get_event_loop().run_until_complete(tellServ())

paramiko not executing basic command on machine

I am trying to execute a basic command on a device using paramiko ("show clock", which displays the time):
#!/usr/bin/python
import paramiko
import time
import re
hostname = 'HIDDEN1'
port = '22'
username = 'admin'
password = 'HIDDEN2'
if __name__ == "__main__":
s = paramiko.SSHClient()
s.load_system_host_keys()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
s.connect(hostname, port, username, password, timeout=3)
command = 'show clock'
print("Starting...")
stdin, stdout, stderr = s.exec_command(command)
s.close()
It doesn't run the command; I'm sure it connects though, since if I purposely make the password incorrect it hangs instead of returning an error. I ensured I can connect manually to the device and run the "show clock" command, but the paramiko snippet doesn't work. This is the error it returns:
Starting...
Traceback (most recent call last):
File "./para2.py", line 21, in <module>
stdin, stdout, stderr = s.exec_command('show clock')
File "/usr/lib/python2.6/site-packages/paramiko/client.py", line 350, in exec_command
chan.exec_command(command)
File "/usr/lib/python2.6/site-packages/paramiko/channel.py", line 213, in exec_command
self._wait_for_event()
File "/usr/lib/python2.6/site-packages/paramiko/channel.py", line 1084, in _wait_for_event
raise e
EOFError
The server might not be allowing exec_command()
Try using the interactive shell
ssh_client = paramiko.SSHClient()
shh_client.connect(#creds)
shell = ssh_client.invoke_shell()
You can now use shell.send() and shell.recv() to execute commands and get back their outputs
http://docs.paramiko.org/en/2.7/api/channel.html#paramiko.channel.Channel.send
http://docs.paramiko.org/en/2.7/api/channel.html#paramiko.channel.Channel.recv
Example: https://www.semicolonworld.com/question/56794/implement-an-interactive-shell-over-ssh-in-python-using-paramiko

asyncio fails to connect to RabbitMQ

I'm learning thenextquant quant framework, but always get connection error while connecting to RabbitMQ. after some troubleshooting, i found asynico/aioamqp module always prompts error:An open stream was garbage collected prior to establishing network connection; call "stream.close()" explicitly.
while trying to connect to RabbitMQ server, RabbitMQ is up and running and other client can connect to it without any error.
Then I followed the hello world example from aioamqp(https://github.com/Polyconseil/aioamqp/blob/master/examples/send.py) to write a test program, then reproduced the error.
import asyncio
import aioamqp
async def send():
transport, protocol = await aioamqp.connect(host="127.0.0.1", port=5672, login="guest", password="guest", login_method="PLAIN")
channel = await protocol.channel()
await channel.queue_declare(queue_name='hello')
await channel.basic_publish(
payload='Hello World!',
exchange_name='',
routing_key='hello'
)
print(" [x] Sent 'Hello World!'")
await protocol.close()
transport.close()
asyncio.get_event_loop().run_until_complete(send())
(venv_380) appledeMBP:Market apple$ python hello.py
An open stream was garbage collected prior to establishing network connection; call "stream.close()" explicitly.
Traceback (most recent call last):
File "hello.py", line 31, in <module>
asyncio.get_event_loop().run_until_complete(send())
File "/Users/apple/.pyenv/versions/3.8.0/lib/python3.8/asyncio/base_events.py", line 608, in run_until_complete
return future.result()
File "hello.py", line 14, in send
transport, protocol = await aioamqp.connect(host="127.0.0.1", port=5672, login="guest", password="guest", login_method="PLAIN")
File "/Users/apple/.virtualenvs/venv_380/lib/python3.8/site-packages/aioamqp/__init__.py", line 59, in connect
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
File "/Users/apple/.pyenv/versions/3.8.0/lib/python3.8/asyncio/trsock.py", line 82, in setsockopt
self._sock.setsockopt(*args, **kwargs)
OSError: [Errno 9] Bad file descriptor
finally I found it's caused by version of Python. the issue is gone once using 3.6 instead of 3.8 which result in connection issue with aioamqp.connect()

Paramiko: failed to re-use ssh session when connecting to Cisco C2960 switcher

I'm trying to write a simple script to connect Cisco C2960 switcher.I just can't figure out how to re-use the ssh session to execute more than two commands.
There's a discussion on SO,
Persistent ssh session to Cisco router
but none of the answers provided there can solve my problem.
Here's my code:
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('xxx',username='xxx',password='xxx',allow_agent=False)
stdin, stdout, stderr = ssh.exec_command('show version')
stdin, stdout, stderr = ssh.exec_command('sh mac brief')
Results in:
Traceback (most recent call last):
File "./test.py", line 10, in <module>
stdin, stdout, stderr = ssh.exec_command('sh mac brief')
File "/usr/lib/python2.6/site-packages/paramiko/client.py", line 363, in exec_command
chan = self._transport.open_session()
File "/usr/lib/python2.6/site-packages/paramiko/transport.py", line 658, in open_session
return self.open_channel('session')
File "/usr/lib/python2.6/site-packages/paramiko/transport.py", line 746, in open_channel
raise e
EOFError
invoke_shell() is best when interacting with Cisco IOS, i tried other fucntions in paramiko but all of them throw buggy EOF file errors
I answered this on the referenced SO question, but did you try using invoke_shell()?
I've seen many reports that some Cisco devices only allow one command execution before closing the connection (this may be configurable somewhere in the device though). In this case, you need to start a shell, and work interactively (or pseudo-interactively like with pexpect), or create a script to send as a single command.

Categories