6

I have some Paramiko code where I use the invoke_shell method to request an interactive ssh shell session on a remote server. Method is outlined here: invoke_shell()

Here's a summary of the pertinent code:

sshClient = paramiko.SSHClient()
sshClient.connect('127.0.0.1', username='matt', password='password')
channel = sshClient.get_transport().open_session()
channel.get_pty()
channel.invoke_shell()

while True:
    command = raw_input('$ ')
    if command == 'exit':
        break

    channel.send(command + "\n")

    while True:
        if channel.recv_ready():
            output = channel.recv(1024)
            print output
        else:
            time.sleep(0.5)
            if not(channel.recv_ready()):
                break

sshClient.close()

My question is: is there a better way to interact with the shell? The above works, but it's ugly with the two prompts (the matt@kali:~$ and the $ from raw_input), as shown in the screenshot of a test run with the interactive shell. I guess I need help writing to the stdin for the shell? Sorry, I don't code much. Thanks in advance! enter image description here

Matt
  • 1,053
  • 4
  • 14
  • 29
  • Thanks @whjm. No purpose other than just writing an SSH client for fun. I would prefer to stick with Paramiko. – Matt Mar 24 '17 at 03:50

2 Answers2

7

I imported a file, interactive.py, found on Paramiko's GitHub. After importing it, I just had to change my code to this:

try:
    import interactive
except ImportError:
    from . import interactive

...
...

channel.invoke_shell()
interactive.interactive_shell(channel)
sshClient.close()
pynexj
  • 19,215
  • 5
  • 38
  • 56
Matt
  • 1,053
  • 4
  • 14
  • 29
  • 1
    on windows: `TypeError: write() argument must be str, not bytes`. Line 87 in `interactive.py` should be changed to: `sys.stdout.write(data.decode("utf8", "ignore"))` – WhyWhat Jan 15 '22 at 12:47
  • I had some issues with control character and line wrapping causing unexpected behaviour with zsh autocompletion. I've modified the demo to support this here: https://gist.github.com/mvanderlee/c6fb0bf7611565e43813bfa503f2afc1 – M.Vanderlee May 30 '23 at 08:40
3

You can try disabling echo after invoking the remote shell:

channel.invoke_shell()
channel.send("stty -echo\n")

while True:
    command = raw_input() # no need for `$ ' anymore
    ... ...
pynexj
  • 19,215
  • 5
  • 38
  • 56