Python Script Pexpect SSH - python

I'm trying to do a Python script (with a loop) to connect in SSH,it works if everything is good ( password and route) but stop when it's not working(wrong password or no routes to host ).Here is the important part of the script, how can I control if everything is working ?
connexion = pexpect.spawn("ssh -o StrictHostKeyChecking=no "+user+"#" + ip )
index=connexion.expect(':')
connexion.sendline(password + "\r")
connexion.expect('>')
connexion.sendline('show clock \r')
connexion.expect('>')
connexion.sendline('exit')
connexion.close()
I get the error :
Traceback (most recent call last):
File "script.py", line 21, in <module>
connexion.expect('>')
File "/usr/lib/python2.7/dist-packages/pexpect/__init__.py", line 1418, in expect
timeout, searchwindowsize)
File "/usr/lib/python2.7/dist-packages/pexpect/__init__.py", line 1433, in expect_list
timeout, searchwindowsize)
File "/usr/lib/python2.7/dist-packages/pexpect/__init__.py", line 1521, in expect_loop
raise EOF(str(err) + '\n' + str(self))
pexpect.EOF: End Of File (EOF). Exception style platform.
<pexpect.spawn object at 0x7fcfeecee750>
version: 3.1
command: /usr/bin/ssh
args: ['/usr/bin/ssh', '-o', 'StrictHostKeyChecking=no', 'username#10.9.128.5']
searcher: <pexpect.searcher_re object at 0x7fcfeecee850>
buffer (last 100 chars): ''
before (last 100 chars): ' connect to host 10.9.128.5 port 22: No route to host\r\r\npassword\r\n\r\n'
Thanks

The problem is that the host 10.9.128.5 was not reachable at the moment.
ssh has returned this message:
connect to host 10.9.128.5 port 22: No route to host
And not that, what was expected.

You are getting an exception which needs to be handled correctly. Below is some code that you can use as an example to pass the exception and log it.
def ignore_exception_out(conn, text, timeout=10):
try:
conn.expect(text, timeout)
except Exception as e:
logging.log("Exception reached {0}".format(e))
pass

Related

Paramiko stuck on for loop

I need to perform a remote software update for a Linux device.
I'm able to upload via SSH and SFTP to /tmp/ folder the .bin file and perform the sysupgrade.
I want to do this on multiple device, so I added a for loop in order to do it.
But, when I run the ssh.exec_command("sysupgrade /tmp/myfile.bin"), something stucks.
Here's my code:
import paramiko
# paths to file
local_path="C:/Users/Desktop/myfile.bin"
remote_path="/tmp/myfile.bin"
# IP
ip_list = ["my_ip_1","my_ip_2"]
password_list=["passw_1","passw_2"]
#Start SSH
ssh = paramiko.client.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# loop for IP and password
for i,n in zip(ip_list,password_list):
print(i,n)
try:
print("Open session in: " + i + "...")
ssh.connect(i, username='root', password=n)
except paramiko.SSHException:
print("Connection Failed")
quit()
# Upload file to /tmp/
print("Uploading file to " + str(i) + " in /tmp/...")
sftp = ssh.open_sftp()
sftp.put(local_path, remote_path)
try:
# Here something stucks
stdin, stdout, stderr = ssh.exec_command("sysupgrade /tmp/myfile.bin", timeout=30)
sysupgrade_response=stdout.readlines()
print(sysupgrade_response)
sftp.close()
ssh.close()
except paramiko.SSHException:
print("Continue with others IP in list...")
sftp.close()
ssh.close()
continue
sftp.close()
ssh.close()
print("\n\n***********************End execution***********************\n\n")
This is the errors I got:
Traceback (most recent call last):
File "C:\Users\AppData\Roaming\Python\Python37\site-packages\paramiko\channel.py", line 699,
in recv
out = self.in_buffer.read(nbytes, self.timeout)
File "C:\Users\AppData\Roaming\Python\Python37\site-packages\paramiko\buffered_pipe.py",
line 164, in read
raise PipeTimeout()
paramiko.buffered_pipe.PipeTimeout
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Python Scripts\myscript.py", line 73, in <module>
sysupgrade_response=stdout.readlines()
File "C:\Users\AppData\Roaming\Python\Python37\site-packages\paramiko\file.py", line 349,
in readlines
line = self.readline()
File "C:\Users\AppData\Roaming\Python\Python37\site-packages\paramiko\file.py", line 291,
in readline
new_data = self._read(n)
File "C:\Users\AppData\Roaming\Python\Python37\site-packages\paramiko\channel.py", line 1361,
in _read
return self.channel.recv(size)
File "C:\Users\AppData\Roaming\Python\Python37\site-packages\paramiko\channel.py", line 701,
in recv
raise socket.timeout()
After the "sysupgrade" command, I would like to close the connection with the first ip in the list ( or handling some errors ) and go on with the for loop and connect to the second ip in the list.
Hope is clear enough
I assume that the sysupgrade restarts the machine or at least the SSH server or networking.
I would guess that if you execute sysupgrade in your SSH client, it will also lose the connection, won't it?

How to fix invalid URL error while using http.client?

I am trying to hit an api using http.client of pyhton3 to simulate how I would do the same in a web browser.
However, http.client feels that url is inappropriate.
This is what I am trying to do.
import http.client
connection = http.client.HTTPSConnection("https://analyticsapi.zoho.com/api/EmailAddress/WorkspaceName/TableName?ZOHO_ACTION=IMPORT&ZOHO_OUTPUT_FORMAT=XML&ZOHO_ERROR_FORMAT=XML&ZOHO_API_VERSION=1.0&authtoken=************&ZOHO_IMPORT_TYPE=APPEND&ZOHO_AUTO_IDENTIFY=TRUE&ZOHO_ON_IMPORT_ERROR=ABORT&ZOHO_CREATE_TABLE=TRUE&ZOHO_FILE=/home/dev1/Desktop/Zoho/temporary.csv")
connection.request("GET", "/")
response = connection.getresponse()
print("Status: {} and reason: {}".format(response.status, response.reason))
connection.close()
And this is the error I am getting.
$ python3 pyToTestPushingCSV.py
Traceback (most recent call last):
File "/usr/lib/python3.5/http/client.py", line 798, in _get_hostport
port = int(host[i+1:])
ValueError: invalid literal for int() with base 10: '//analyticsapi.zoho.com/api/usename/ATable/InsideTable?ZOHO_ACTION=IMPORT&ZOHO_OUTPUT_FORMAT=XML&ZOHO_ERROR_FORMAT=XML&ZOHO_API_VERSION=1.0&authtoken=****
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "pyToTestPushingCSV.py", line 3, in <module>
connection = http.client.HTTPSConnection("https://analyticsapi.zoho.com/api/usename/ATable/InsideTable?ZOHO_ACTION=IMPORT&ZOHO_OUTPUT_FORMAT=XML&ZOHO_ERROR_FORMAT=XML&ZOHO_API_VERSION=1.0&authtoken=****************&ZOHO_IMPORT_TYPE=APPEND&ZOHO_AUTO_IDENTIFY=TRUE&ZOHO_ON_IMPORT_ERROR=ABORT&ZOHO_CREATE_TABLE=TRUE&ZOHO_FILE=/home/dev1/Desktop/Zoho/temporary.csv")
File "/usr/lib/python3.5/http/client.py", line 1233, in __init__
source_address)
File "/usr/lib/python3.5/http/client.py", line 762, in __init__
(self.host, self.port) = self._get_hostport(host, port)
File "/usr/lib/python3.5/http/client.py", line 803, in _get_hostport
raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
http.client.InvalidURL: nonnumeric port: '//analyticsapi.zoho.com/api/usename/ATable/InsideTable?ZOHO_ACTION=IMPORT&ZOHO_OUTPUT_FORMAT=XML&ZOHO_ERROR_FORMAT=XML&ZOHO_API_VERSION=1.0&authtoken=*************&ZOHO_IMPORT_TYPE=APPEND&ZOHO_AUTO_IDENTIFY=TRUE&ZOHO_ON_IMPORT_ERROR=ABORT&ZOHO_CREATE_TABLE=TRUE&ZOHO_FILE=/home/dev1/Desktop/Zoho/temporary.csv'
When I hit the URL with my Browser it gives a good response back in XML which in short, succeeds.
This is where I referred for documentation
Can you pin point where I went wrong?
As per documentation HTTPS support is only available if Python was compiled with SSL support (through the ssl module).
Also the default port for https connection is 443. The module seems to be hitting that port by default.

How to fetch sizes of all SFTP files in a directory through Paramiko

import paramiko
from socket import error as socket_error
import os
server =['10.10.0.1','10.10.0.2']
path='/home/test/'
for hostname in server:
try:
ssh_remote =paramiko.SSHClient()
ssh_remote.set_missing_host_key_policy(paramiko.AutoAddPolicy())
privatekeyfile = os.path.expanduser('~/.ssh/id')
mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile, password='test123')
ssh_remote.connect(hostname, username = 'test1', pkey = mykey)
sftp=ssh_remote.open_sftp()
for i in sftp.listdir(path):
info = sftp.stat(i)
print info.st_size
except paramiko.SSHException as sshException:
print "Unable to establish SSH connection:{0}".format(hostname)
except socket_error as socket_err:
print "Unable to connect connection refused"
This is my code. I tried to get file size of remote server files. But below error was throwing. Can some please guide on this?
Error
Traceback (most recent call last):
File "<stdin>", line 15, in <module>
File "/usr/lib/python2.6/site-packages/paramiko/sftp_client.py", line 337, in stat
t, msg = self._request(CMD_STAT, path)
File "/usr/lib/python2.6/site-packages/paramiko/sftp_client.py", line 624, in _request
return self._read_response(num)
File "/usr/lib/python2.6/site-packages/paramiko/sftp_client.py", line 671, in _read_response
self._convert_status(msg)
File "/usr/lib/python2.6/site-packages/paramiko/sftp_client.py", line 697, in _convert_status
raise IOError(errno.ENOENT, text)
IOError: [Errno 2] No such file
SFTPClient.listdir returns file names only, not a full path. So to use the filename in another API, you have to add a path:
for i in sftp.listdir(path):
info = sftp.stat(path + "/" + i)
print info.st_size
Though that's inefficient. Paramiko knows the size already, you are just throwing the information away by using SFTPClient.listdir instead of SFTPClient.listdir_attr (listdir calls listdir_attr internally).
for i in sftp.listdir_attr(path):
print i.st_size

Proxycommand in paramiko

I'm trying to do a simple proxycommand using paramiko in python.
Basically I'm trying to replicate the behaviour of this ssh command:
ssh -i ~/.ssh/destination_key user#destination.test.internal -o 'ProxyCommand ssh -i ~/.ssh/jumpbox_key -W %h:%p user#jumpbox.test.internal'
The above works as expected amd connects to destination.test.internal.
I'm trying to do the same thing in python with the following on the same box:
#!/usr/bin/python3
import paramiko
import argparse
addresses = ["destination.test.internal"];
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
proxy = paramiko.ProxyCommand("ssh -i ~/.ssh/jumpbox_key -W %h:%p user#jumpbox.test.internal")
for address in addresses:
#Connect over ssh to each server
try:
ssh.connect(address , username='user', key_filename="~/.ssh/destination_key", sock = proxy )
except paramiko.AuthenticationException:
print ("Authentication Failed")
except paramiko.SSHException:
print ("Connection Failed")
stdin,stdout,stderr = ssh.exec_command('ls -l')
print (stdout.readlines())
ssh.close()
Needless to say this isn't working. It's failing with:
Traceback (most recent call last):
Exception: Error reading SSH protocol banner
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 1893, in _check_banner
buf = self.packetizer.readline(timeout)
File "/usr/local/lib/python3.5/dist-packages/paramiko/packet.py", line 331, in readline
buf += self._read_timeout(timeout)
File "/usr/local/lib/python3.5/dist-packages/paramiko/packet.py", line 501, in _read_timeout
raise socket.timeout()
socket.timeout
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 1749, in run
self._check_banner()
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 1897, in _check_banner
raise SSHException('Error reading SSH protocol banner' + str(e))
paramiko.ssh_exception.SSHException: Error reading SSH protocol banner
Connection Failed
Traceback (most recent call last):
File "./log_file_fix.py", line 31, in <module>
stdin,stdout,stderr = ssh.exec_command('ls -l')
File "/usr/local/lib/python3.5/dist-packages/paramiko/client.py", line 436, in exec_command
chan = self._transport.open_session(timeout=timeout)
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 716, in open_session
timeout=timeout)
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 800, in open_channel
raise SSHException('SSH session not active')
paramiko.ssh_exception.SSHException: SSH session not active
However I'm not sure where I'm going wrong.
Instead of %h:%p, Specify host and port inside paramiko.ProxyCommand()
proxy = paramiko.ProxyCommand("ssh -i ~/.ssh/jumpbox_key -W DESTINATION_HOST_ADDRESS:22 user#jumpbox.test.internal")
You have to change your code like below:
#!/usr/bin/python3
import paramiko
import argparse
addresses = ["destination.test.internal"];
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for address in addresses:
proxy_jump_command='ssh -i ~/.ssh/jumpbox_key -W {HOST}:{PORT} user#jumpbox.test.internal'.format(HOST=address, PORT=22)
proxy = paramiko.ProxyCommand(proxy_jump_command)
#Connect over ssh to each server
try:
ssh.connect(address , username='user', key_filename="~/.ssh/destination_key", sock = proxy )
except paramiko.AuthenticationException:
print ("Authentication Failed")
except paramiko.SSHException:
print ("Connection Failed")
stdin,stdout,stderr = ssh.exec_command('ls -l')
print (stdout.readlines())
ssh.close()

Linux Virtual Serial Port for creating a device commuication

I created a VSP using SOCAT with below command:
socat -d -d pty,raw,echo=0 pty,raw,echo=0
where I was able create a serial device (19200,N,8,1) and send and receive data using Python.
So I have to do the same for one more device with config of (19200,even_aprity,hardware flow in Python) when I do that its throwing below error:
Traceback (most recent call last):
File "py2.py", line 163, in <module>
buffer += ser.read(1) # this will block until one more char or timeout
File "/usr/lib/python2.6/dist-packages/serial/serialposix.py", line 311, in read
if self.fd is None: raise portNotOpenError
serial.serialutil.SerialException: Port not open
Exception SystemError: 'error return without exception set' in <bound method BreakHandler.__del__ of <sig_handler.BreakHandler instance at 0xb719338c>> ignored
Guide me

Categories