23

i'm new on python. i wrote a script to connect to a host and execute one command

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=user, password=pw)

print 'running remote command'

stdin, stdout, stderr = ssh.exec_command(command)
stdin.close()

for line in stdout.read().splitlines():
    print '%s$: %s' % (host, line)
    if outfile != None:
        f_outfile.write("%s\n" %line)

for line in stderr.read().splitlines():
    print '%s$: %s' % (host, line + "\n")
    if outfile != None:
        f_outfile.write("%s\n" %line)

ssh.close()

if outfile != None:
    f_outfile.close()

print 'connection to %s closed' %host

except:
   e = sys.exc_info()[1]
   print '%s' %e

works fine when then remote command doesn't need a tty. i found an invoke_shell example Nested SSH session with Paramiko. i'm not happy with this solution, because if a server has an prompt that isn't specified in my script -> infinite loop or a specified prompt in the script is a string in the return text -> not all data will be received. is there a better solution maybe where stdout and stderr are send back like in my script?

Community
  • 1
  • 1
user1008764
  • 390
  • 1
  • 3
  • 7
  • Mind that this answer does not use an SSH key and therefore a pw is needed. With SSH key, you do not need a pw and pass the key_filename parameter instead. – questionto42 Jan 22 '22 at 18:37

6 Answers6

36

There is something wrong with the accepted answer, it sometimes (randomly) brings a clipped response from server. I do not know why, I did not investigate the faulty cause of the accepted answer because this code worked perfectly for me:

import paramiko

ip='server ip'
port=22
username='username'
password='password'

cmd='some useful command' 

ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,port,username,password)

stdin,stdout,stderr=ssh.exec_command(cmd)
outlines=stdout.readlines()
resp=''.join(outlines)
print(resp)

stdin,stdout,stderr=ssh.exec_command('some really useful command')
outlines=stdout.readlines()
resp=''.join(outlines)
print(resp)
Raiden Core
  • 1,535
  • 12
  • 13
27

There is extensive paramiko API documentation you can find at: http://docs.paramiko.org/en/stable/index.html

I use the following method to execute commands on a password protected client:

import paramiko

nbytes = 4096
hostname = 'hostname'
port = 22
username = 'username' 
password = 'password'
command = 'ls'

client = paramiko.Transport((hostname, port))
client.connect(username=username, password=password)

stdout_data = []
stderr_data = []
session = client.open_channel(kind='session')
session.exec_command(command)
while True:
    if session.recv_ready():
        stdout_data.append(session.recv(nbytes))
    if session.recv_stderr_ready():
        stderr_data.append(session.recv_stderr(nbytes))
    if session.exit_status_ready():
        break

print 'exit status: ', session.recv_exit_status()
print ''.join(stdout_data)
print ''.join(stderr_data)

session.close()
client.close()
Community
  • 1
  • 1
ThePracticalOne
  • 641
  • 1
  • 8
  • 12
0

The code of @ThePracticalOne is great for showing the usage except for one thing: Somtimes the output would be incomplete.(session.recv_ready() turns true after the if session.recv_ready(): while session.recv_stderr_ready() and session.exit_status_ready() turned true before entering next loop)

so my thinking is to retrieving the data when it is ready to exit the session.

while True:
if session.exit_status_ready():
while True:
    while True:
        print "try to recv stdout..."
        ret = session.recv(nbytes)
        if len(ret) == 0:
            break
        stdout_data.append(ret)

    while True:
        print "try to recv stderr..."
        ret = session.recv_stderr(nbytes)
        if len(ret) == 0:
            break
        stderr_data.append(ret)
    break
0

Passwordless SSH worked for me

import paramiko

def connect_SSH():
    ssh = paramiko.SSHClient()
    username = '<uname>'
    port = <port-no>
    ip = '<ip-address>'
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(ip,port,username)

    stdin, stdout, stderr = ssh.exec_command('<cmd>')
    outlines = stdout.readlines()
    resp=''.join(outlines)
    print(resp) 
connect_SSH()
Rajeev
  • 119
  • 4
0

ThePracticalOne - you are hero! I had problems with exec_command (which is a member of Client) I tried to run powershell commands over ssh on Windows server, and only your example with

client = paramiko.Transport((hostname, port))
client.connect(username=username, password=password)

and

 while True:
        if session.recv_ready():
            stdout_data.append(session.recv(nbytes))
        if session.recv_stderr_ready():
            stderr_data.append(session.recv_stderr(nbytes))
        if session.exit_status_ready():
            break

helped to me!

Viacheslav
  • 26
  • 3
-1
###### Use paramiko to connect to LINUX platform############
import paramiko

ip='server ip'
port=22
username='username'
password='password'
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,port,username,password)

--------Connection Established-----------------------------

######To run shell commands on remote connection###########
import paramiko

ip='server ip'
port=22
username='username'
password='password'
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,port,username,password)


stdin,stdout,stderr=ssh.exec_command(cmd)
outlines=stdout.readlines()
resp=''.join(outlines)
print(resp) # Output 
  • 1
    Refer to : Refer to : https://github.com/sarthakjain1811/Python-Scripts/blob/master/Connect%20to%20remote%20linux%20connection%20and%20run%20shell%20commands – Sarthak Jain Apr 26 '20 at 12:41