user11185808
user11185808

Reputation: 83

Unable to execute some unix commands with paramiko (which I can with pexpect)

This is my first posting (and I am a relative python newbie) so please excuse any faux pas. I have researched this and can’t seem to find a solution and any help will be appreciated.

On My Mac

from pexpect import pxssh

def use_pexpect(command):       
    s = pxssh.pxssh()
    s.login("hostname", "login", "password")
    s.sendline(command)
    s.prompt()
    print s.before.replace(command, "").strip()

use_pexpect('echo $unit0')

Shows (as expected) "/usr2/product/myarea/data/unit0"

$unit0 being something that is used as proprietary setup and in context to our product. If I were to log into our unix server (via terminal) as ssh login@hostname and do "echo $unit0" from the prompt I’d get “/usr2/product/myarea/data/unit0”

Sadly while running the above on Windows it would not run because of the error below.

ImportError: cannot import name spawn

It seems pexpect spawn will not work on windows

So it appeared paramiko would potentially solve my problem and yet….when I run below..

import paramiko

def use_paramiko(command):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect("hostname", username = "login", password = "password")
    stdin, stdout, stderr = ssh.exec_command(command)
    print stdout.readline()

use_paramiko('echo $unit0')

returns nothing (and this holds true for any ‘proprietary’ commands or shell scripts that contain environment variables I may choose to run). However if i run a standard unix command as below:

use_paramiko('pwd')

does return

/usr2/product/myarea

Please note that the following variations did not work either (i.e. returned nothing):

stdin, stdout, stderr = ssh.exec_command(command, get_pty=True)

Or

chan = ssh.get_transport().open_session()
chan.get_pty()
chan.exec_command(command)
print chan.recv(1024)

So it appears while pexpect will get the unix server the execute the command as if being run natively on the unix box and return the results, paramiko only seems able to cope with standard unix commands and not proprietary ones.

So really the question is how do I replicate the pexpect function via paramiko (or indeed anything else that will work on windows as well)

Upvotes: 0

Views: 1152

Answers (1)

user11185808
user11185808

Reputation: 83

Upon further research (url below) i seem to have a handle on this.

Python, paramiko, invoke_shell and ugly characters

This worked:

import paramiko
from time import sleep

def use_paramiko(command):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect("hostname", username = "login", password = "password")
    channel = ssh.invoke_shell()
    channel.send(command + "\n")
    sleep(1)
    print channel.recv(1024)
    ssh.close()

use_paramiko('echo $unit0')

Which returns a lot more info than I need. As below:

Last login: Mon Mar 11 15:47:46 2019 from mymac
stty: missing argument to ‘erase’
Try 'stty --help' for more information.
echo $unit0

Current Terminal Number [ 514 ] 


K.username.13% echo $unit0
/usr2/product/myarea/data/unit0
K.username.14% 

Nonetheless at least i can get it to do what I like it to (although the response will need some cleaning up).

Two things to note (which caught me out initially).

1- The '\n' after the command is necessary otherwise the command does not execute.

2 - As is the sleep otherwise it will only return the first line (i.e. "Last login: Mon Mar 11 15:47:46 2019 from mymac"). Presumably there is a more elegant way to wait until the command finishes executing but gets me over my immediate problem.

Thanks to posters on the url above. Hope this helps someone down the line (any suggestions to improve the above answer gratefully received)

Upvotes: 1

Related Questions