I've been trying to run commands on an Overture Box using paramiko to establish the SSH connection.
My script does connect properly to the box, no issues are seen, the problem comes when the script runs the exec_command(cmd) method:
Traceback (most recent call last):
File "test.py", line 39, in <module>
stdin, stdout, stderr = ssh.exec_command("version")
File "/opt/csw/lib/python2.7/site-packages/paramiko/client.py", line 345, in exec_command
chan.exec_command(command)
File "/opt/csw/lib/python2.7/site-packages/paramiko/channel.py", line 60, in _check
return func(self, *args, **kwds)
File "/opt/csw/lib/python2.7/site-packages/paramiko/channel.py", line 229, in exec_command
self._wait_for_event()
File "/opt/csw/lib/python2.7/site-packages/paramiko/channel.py", line 1086, in _wait_for_event
raise e
paramiko.ssh_exception.SSHException: Channel closed.
Same script using a Linux Box as the target host yields the proper results
The code is borrowed, I just found the snippet Googling:
import sys
import time
import select
import paramiko
host = raw_input("Hostname?: ")
i = 1
password = raw_input("Password?: ")
#
# Try to connect to the host.
# Retry a few times if it fails.
#
while True:
print "Trying to connect to %s (%i/30)" % (host, i)
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, port=22, username="username", password=password)
print "Connected to %s" % host
break
except paramiko.AuthenticationException:
print "Authentication failed when connecting to %s" % host
sys.exit(1)
except:
print "Could not SSH to %s, waiting for it to start" % host
i += 1
time.sleep(2)
# If we could not connect within time limit
if i == 30:
print "Could not connect to %s. Giving up" % host
sys.exit(1)
# Send the command (non-blocking)
stdin, stdout, stderr = ssh.exec_command("version")
# Wait for the command to terminate
while not stdout.channel.exit_status_ready():
# Only print data if there is data to read in the channel
if stdout.channel.recv_ready():
rl, wl, xl = select.select([stdout.channel], [], [], 0.0)
if len(rl) > 0:
# Print data from stdout
print stdout.channel.recv(1024),
#
# Disconnect from the host
#
print "Command done, closing SSH connection"
ssh.close()
I found other questions where it's said that the issue might be related to the SFTP settings in the host, but I'm able to do:
sftp username#hostname
I've Googled for a while but I can't find anything helpful so far.
Thanks in advance for your help.
EDIT: Almost forgot, I know the issue is exactly at:
stdin, stdout, stderr = ssh.exec_command("version")
I've run the whole script interactively and it breaks when I run that line.
Could be that the Overture does not support the SSH exec_command request.
I have needed to use transport.open_session(), and session.get_pty() and session.invoke_shell() to setup an interactive shell session, then use session.send() and session.recv() to write/read to the shell session for Cisco switches and other network appliances, when exec_command() is not available.
here is a workaround for this,
get a transport for your connection.
open a session.
then exec_command(command) and thenrecv()`, no need for sleep.
client.connect("host", port=22, username="user",password= "pass",look_for_keys=False, allow_agent=False)
transport=client.get_transport()
channel = t.open_session()
channel.exec_command(command)
out = channel.recv(-1)
print(out.decode())
Related
I am trying to build a Python script using Paramiko which should SSH Linux server and execute a command, some commands output is working for example df -f,netstat but some of them aren't for example onstat -,ifconfig. Need help solving this issue.
#!/usr/pkg/bin/python
#Importing modules
import paramiko
import time
#setting parameters like host IP, username, passwd and number of iterations to gather cmds
HOST = 'x.x.x.x'
USER = 'abc'
PASS = 'efg'
ITERATION = 3
client1=paramiko.SSHClient()
#Add missing client key
client1.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#connect to CUCM
client1.connect(HOST,username=USER,password=PASS)
print("SSH connection to %s established" %HOST)
#Gather commands and read the output from stdout
stdin, stdout, stderr = client1.exec_command("onstat -")
time.sleep(2)
for line in stdout.readlines():
print(line)
client1.close()
print("Logged out of device %s" %HOST)
Any thought how to resolve this?
I know exec_command returns 3 streams, but I'm unable to print the output as it should arrive to these streams.
client = SSHClient()
client.load_system_host_keys()
client.connect('ssh.example.com')
stdin, stdout, stderr = client.exec_command('ls -l; sleep 10; ls -l')
for line in stdout.readlines():
print line
for line in stderr.readlines():
print line
This seems to output new lines only at the end when the entire command has been finished. I'd like to receive the characters as they are generated by the remote commands. Is this possible?
To read the output on your terminal, the method i knew is to stream the readbinaries and writebinaries straight from the ssh session into your terminal
import paramiko
import os
import sys
host_address = ''
USER = ''
PASSWORD = ''
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host_address, user=USER, password=PASSWORD)
#Time to invoke the shell from paramiko support
client_shell = client.INVOKE_SHELL()
standard_input = client_shell.makefile('wb')
standard_output = client_shell.makefile('rb')
standard_input.write('''
ls -l
sleep 10
ls -l
''')
print standard_output.read()
#Close all the streams and ssh connection in the end to flush the session
standard_input.close()
standard_output.close()
client.close()
I am writing a script in Python for login to ssh and read the output of commands just executed. I am using paramiko package for this. I am trying to execute command "top" and get its output printed on the console. However, I am not able to do this. Please find the snippet:
import sys
import time
import select
import paramiko
host = 'localhost'
i = 1
#
# Try to connect to the host.
# Retry a few times if it fails.
#
while True:
print 'Trying to connect to %s (%i/30)' % (host, i)
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, port=22, username='dummy', password='dummy')
print "Connected to %s" % host
break
except paramiko.AuthenticationException:
print "Authentication failed when connecting to %s" % host
sys.exit(1)
except:
print "Could not SSH to %s, waiting for it to start" % host
i += 1
time.sleep(2)
# If we could not connect within time limit
if i == 30:
print "Could not connect to %s. Giving up" % host
sys.exit(1)
# Send the command (non-blocking)
stdin, stdout, stderr = ssh.exec_command("uname")
# Wait for the command to terminate
while not stdout.channel.exit_status_ready():
# Only print data if there is data to read in the channel
if stdout.channel.recv_ready():
rl, wl, xl = select.select([stdout.channel], [], [], 0.0)
if len(rl) > 0:
# Print data from stdout
print '-------------------------------'
print stdout.channel.recv(1024)
print '-------------------------------'
# Send the command (non-blocking)
stdin, stdout, stderr = ssh.exec_command("top -n 1")
# Wait for the command to terminate
while not stdout.channel.exit_status_ready():
# Only print data if there is data to read in the channel
if stdout.channel.recv_ready():
rl, wl, xl = select.select([stdout.channel], [], [], 0.0)
if len(rl) > 0:
# Print data from stdout
print '-------------------------------'
print stdout.channel.recv(1024)
print '-------------------------------'
# Send the command (non-blocking)
stdin, stdout, stderr = ssh.exec_command("uname")
# Wait for the command to terminate
while not stdout.channel.exit_status_ready():
# Only print data if there is data to read in the channel
if stdout.channel.recv_ready():
rl, wl, xl = select.select([stdout.channel], [], [], 0.0)
if len(rl) > 0:
# Print data from stdout
print '-------------------------------'
print stdout.channel.recv(1024)
print '-------------------------------'
#
# Disconnect from the host
#
print "Command done, closing SSH connection"
ssh.close()
Output:
Trying to connect to localhost (1/30)
Connected to localhost
Linux
-------------------------------
Linux
Command done, closing SSH connection
I am not sure, where I am doing wrong. I am able to get output of other linux commands though. But not sure, why top command's output is not getting printed.
as Jason S pointed out
stdin, stdout, stderr = ssh.exec_command("top -b -n1")
print stdout.read()
works just fine.
top normally uses curses for display rather than just printing. Try the -b for batch option along with the -n 1 you have (top options vary by platform, check the manpage). And in the future, try isolating the problem more - if you were to invoke top via ssh on the command line without your script you would still have an issue.
I am trying to execute a sudo command on a remote machine using python-paramiko, when I execute the command, I bind it with 3 streams, and I use the input stream to pass the password, but it doesn't work, this is the traceback result:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/paramiko/file.py", line 314, in write
self._write_all(data)
File "/usr/local/lib/python2.7/dist-packages/paramiko/file.py", line 439, in _write_all
count = self._write(data)
File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 1263,in _write
self.channel.sendall(data)
File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 796, in sendall
raise socket.error('Socket is closed')
error: Socket is closed
and this is my python code:
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.0.104', username='cdc',password='123456')
stdin, stdout, stderr = ssh.exec_command("sudo dmesg")
stdin.write("123456\n")
stdin.flush()
print stdout.readlines()
ssh.close()
Any help? Thanks in advance
First of all, have you tried in console with ssh cdc#192.168.0.104 "sudo -S -p '' dmesg". If it also fails, then you might check the sshd settings and the sudoer settings.
If it works well, please add some echo between lines, so that we can know exactly when the exception was thrown. I highly doubt that you should change sudo dmesg to sudo -S -p '' dmesg.
You might also try my wrapper of paramiko. I can use it smoothly to access any CentOS/SuSE node and perform any commands (w/wo sudo privilege):
#!/usr/bin/python
from StringIO import StringIO
import paramiko
class SshClient:
"A wrapper of paramiko.SSHClient"
TIMEOUT = 4
def __init__(self, host, port, username, password, key=None, passphrase=None):
self.username = username
self.password = password
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
if key is not None:
key = paramiko.RSAKey.from_private_key(StringIO(key), password=passphrase)
self.client.connect(host, port, username=username, password=password, pkey=key, timeout=self.TIMEOUT)
def close(self):
if self.client is not None:
self.client.close()
self.client = None
def execute(self, command, sudo=False):
feed_password = False
if sudo and self.username != "root":
command = "sudo -S -p '' %s" % command
feed_password = self.password is not None and len(self.password) > 0
stdin, stdout, stderr = self.client.exec_command(command)
if feed_password:
stdin.write(self.password + "\n")
stdin.flush()
return {'out': stdout.readlines(),
'err': stderr.readlines(),
'retval': stdout.channel.recv_exit_status()}
if __name__ == "__main__":
client = SshClient(host='host', port=22, username='username', password='password')
try:
ret = client.execute('dmesg', sudo=True)
print " ".join(ret["out"]), " E ".join(ret["err"]), ret["retval"]
finally:
client.close()
Im sorry i dont have time for details answer but i was able to implement sudo commands on paramiko using this advise
#!/usr/bin/env python
import paramiko
l_password = "yourpassword"
l_host = "yourhost"
l_user = "yourusername"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(l_host, username=l_user, password=l_password)
transport = ssh.get_transport()
session = transport.open_session()
session.set_combine_stderr(True)
session.get_pty()
#for testing purposes we want to force sudo to always to ask for password. because of that we use "-k" key
session.exec_command("sudo -k dmesg")
stdin = session.makefile('wb', -1)
stdout = session.makefile('rb', -1)
#you have to check if you really need to send password here
stdin.write(l_password +'\n')
stdin.flush()
for line in stdout.read().splitlines():
print 'host: %s: %s' % (l_host, line)
I know this question is kind of old but I was wanting to use sudo and paramiko together, too. It took me a while to figure out this solution. It may not work for everyone but I figured it was worth adding.
def ssh_handler(hostname, username=USER, password=PASS, command=CMD):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname,
username=username,
password=password)
# set get_pty to True to get a pseudo terminal
stdin, stdout, stderr = ssh.exec_command(prepare_command(command), get_pty=True)
# write and flush the password to the remote terminal
# note that the password will also be written to the terminal from where the script is executed.
stdin.write(password+'\n')
stdin.flush()
response = stdout.read()
ssh.close()
print(response)
def prepare_command(command):
if (not isinstance(command, basestring)):
command = ' ; '.join(command)
command = command.replace('"','\"')
command = 'sudo -s -- " '+command+' " \n'
return command
# kind of a dumb example but you get the point
mycmd = [];
mycmd.append('cd /dir/this/user/doesnt/have/access/to')
mycmd.append('ls -las')
mycmd.append('cat file_in_dir.txt')
ssh_handler(server, command=mycmd)
I was able to implement this solution which was found in other Stackoverflow threads.
https://www.reddit.com/r/learnpython/comments/60taz7/execute_sudo_su_and_input_password_with_paramiko/df94q7s/
The solution for me was to use invoke_shell() when requiring the use of commands with sudo.
so I was working with paramiko for some basic SSH testing and I'm not getting any output into stdout. Heres my code.
import paramiko
client=paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
com="ls ~/desktop"
client.connect('MyIPAddress',MyPortNumber, username='username', password='password')
output=""
stdin, stdout, stderr = client.exec_command(com)
print "ssh succuessful. Closing connection"
client.close()
print "Connection closed"
stdout=stdout.readlines()
print stdout
print com
for line in stdout:
output=output+line
if output!="":
print output
else:
print "There was no output for this command"
So whenever I run this, the command is executed (as seen by if I do something like a cp, the file is copied), but I always get "There was no output for this command". When stdout=stdout.readlines() is printed, [] is the output. In addition, if I add a print statement into the for loop, it never gets run. Could someone help me out here? Thanks!
You have closed the connection before reading lines:
import paramiko
client=paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
com="ls ~/desktop"
client.connect('MyIPAddress',MyPortNumber, username='username', password='password')
output=""
stdin, stdout, stderr = client.exec_command(com)
print "ssh succuessful. Closing connection"
stdout=stdout.readlines()
client.close()
print "Connection closed"
print stdout
print com
for line in stdout:
output=output+line
if output!="":
print output
else:
print "There was no output for this command"
The code in the accepted answer may hang, if the command produces also an error output. See Paramiko ssh die/hang with big output.
An easy solution, if you do not mind merging stdout and stderr, is to combine them into one stream using Channel.set_combine_stderr:
stdin, stdout, stderr = client.exec_command(command)
stdout.channel.set_combine_stderr(True)
output = stdout.readlines()
If you need to read the outputs separately, see Run multiple commands in different SSH servers in parallel using Python Paramiko.
*Interactive example :
====Part 1, this show the sh output in server ,at the end of is ">"
need some input to continual or exit ======
selilsosx045:uecontrol-CXC_173_6456-R32A01 lteue$ ./uecontrol.sh -host localhost
UE Control:Start UE control using:
UE Control:java -Dlogdir= -Duecontrol.configdir=./etc -jar ./server/server-R32A01.jar -host localhost
Loading properties from file /Users/lteue/Downloads/uecontrol-CXC_173_6456-R32A01/etc/uecontrol.properties
Starting remote CLI towards host localhost
Enter the command Q to exit the CLI, or the command HELP
to get information on available commands.
The CLI is ready for input.
uec>
===========Pyhton code with peramiko ============*
Try below method : while not stdout.channel.exit_status_ready():
def shCommand(server_list):
server_IP = server_list[0]
username = server_list[1]
password = server_list[2]
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(server_IP,22,username, password)strong text
commandList = ['list \n']
alldata = getUeInfo(ssh,commandList)
ssh.close()
def getUeInfo(ssh,commandList):
data_buffer = ""
num_of_input = 0
stdin, stdout, stderr = ssh.exec_command('cmd')
while not stdout.channel.exit_status_ready():
solo_line = ""
if stdout.channel.recv_ready():
solo_line = stdout.channel.recv(1024) # Retrieve the first 1024 bytes
data_buffer += solo_line
if(cmp(solo_line,'uec> ') ==0 ): #len of solo should be 5 ,
if num_of_input == 0 :
data_buffer = ""
for cmd in commandList :
#print cmd
stdin.channel.send(cmd)
num_of_input += 1
if num_of_input == 1 :
stdin.channel.send('q \n')
num_of_input += 1
return data_buffer
As #jabaldonedo said you closed your SSHClient connection before reading the stdout. SSHClient can be used as a context manager. Using the SSHClient as a context manager helps prevent you from trying to access stdout and stderr after the ssh connection is closed. The resulting code in Python3 syntax looks like:
from paramiko import AutoAddPolicy, SSHClient
with SSHClient() as client:
client.set_missing_host_key_policy(AutoAddPolicy)
client.connect(
'MyIPAddress',
MyPortNumber,
username='username',
password='password'
)
com = "ls ~/desktop"
stdin, stdout, stderr = client.exec_command(com)
output = ''
for line in stdout.readlines()
output += line
if output:
print(output)
else:
print("There was no output for this command")
# Program to print the output in console/interpreter/shell in runtime without using stdout.
import paramiko
import xlrd
import time
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
loc = ('/Users/harshgow/Documents/PYTHON_WORK/labcred.xlsx')
wo = xlrd.open_workbook(loc)
sheet = wo.sheet_by_index(0)
Host = sheet.cell_value(0, 1)
Port = int(sheet.cell_value(3, 1))
User = sheet.cell_value(1, 1)
Pass = sheet.cell_value(2, 1)
def details(Host, Port, User, Pass):
time.sleep(2)
ssh.connect(Host, Port, User, Pass)
print('connected to ip ', Host)
stdin = ssh.exec_command("")
remote_conn = ssh.invoke_shell()
print("Interactive SSH session established")
output = remote_conn.recv(1000)
remote_conn.send("\n")
remote_conn.send("xstatus Cameras\n")
time.sleep(5)
output = remote_conn.recv(10000)
print(output)
details(Host, Port, User, Pass)