Paramiko stuck on for loop - python

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?

Related

How to run a program in Paramiko's SSH ProxyCommand

I'm pretty new with Paramiko and python in general. I'm trying to connect to a server and execute some commands on it by ssh through the use of Paramiko's API and a program called Pomerium. My ssh config file is as shown below
Host *.stg-id-proxy.lab.com
ProxyCommand pomerium-cli tcp --listen - %h:%p
User placeholder
and my python code in file "ssh4.py" is as follows
import paramiko
host = "place.stg-id-proxy.lab.com"
port = 22
username = "placeholder"
password = "pass#!#"
command = "pwd"
proxy = paramiko.ProxyCommand("pomerium-cli tcp --listen - %h:%p")
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, port, username, password, allow_agent=False, look_for_keys=False, sock=proxy, banner_timeout=60)
stdin, stdout, stderr = ssh.exec_command(command)
lines = stdout.readlines()
print(lines)
but when I tried running:
python3 ssh4.py
I keep getting the following error
Exception (client): Error reading SSH protocol banner
Traceback (most recent call last):
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/transport.py", line 2271, in _check_banner
buf = self.packetizer.readline(timeout)
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/packet.py", line 380, in readline
buf += self._read_timeout(timeout)
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/packet.py", line 622, in _read_timeout
raise socket.timeout()
socket.timeout
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/transport.py", line 2094, in run
self._check_banner()
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/transport.py", line 2275, in _check_banner
raise SSHException(
paramiko.ssh_exception.SSHException: Error reading SSH protocol banner
Traceback (most recent call last):
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/transport.py", line 2271, in _check_banner
buf = self.packetizer.readline(timeout)
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/packet.py", line 380, in readline
buf += self._read_timeout(timeout)
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/packet.py", line 622, in _read_timeout
raise socket.timeout()
socket.timeout
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "ssh4.py", line 11, in <module>
ssh.connect(host, port, username, password, allow_agent=False, look_for_keys=False, sock=proxy, banner_timeout=60)
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/client.py", line 406, in connect
t.start_client(timeout=timeout)
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/transport.py", line 699, in start_client
raise e
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/transport.py", line 2094, in run
self._check_banner()
File "/Users/placeholder/Library/Python/3.8/lib/python/site-packages/paramiko/transport.py", line 2275, in _check_banner
raise SSHException(
paramiko.ssh_exception.SSHException: Error reading SSH protocol banner
So, any help would be appreciated. Also documentation for Pomerium can be found here:
https://github.com/pomerium/cli
Thank you in advance.

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()

Python Script Pexpect SSH

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

Python FTP (from ftplib module) fails on login to SFTP server

I am doing the following
>> from ftplib import FTP
>> s = FTP('host','user','password') # Connect
and it fails giving the following
Traceback (most recent call last): File "<stdin>", line 1, in <module>
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ftplib.py", line 117, in __init__
self.connect(host)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ftplib.py", line 132, in connect
self.sock = socket.create_connection((self.host, self.port), self.timeout)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 571, in create_connection
raise err socket.error: [Errno 60] Operation timed out
I know that host, user, passwd are correct
How do I debug/fix this error?
WinSCP (which you've otherwise been using to connect to the same server) supports SFTP and SCP, not FTP.
To write a Python program using SFTP, you should be using the Paramiko library.
Try doing it like this:
try:
s = FTP(host)
s.login(user, password)
except Exception, e:
print "The error was:", str(e)

Categories