Search code examples
pythonsshterminalparamikoansi-escape

How do I start a shell without terminal emulation in Python Paramiko?


Is there a way to start a shell without terminal emulation in Python Paramiko?

  • I have tried using exec_command but I really need an interactive shell.
  • Using invoke_shell() I get a terminal and can issue commands, but from Windows 10 OpenSSH server I get an output with ANSI escape sequences, including H code, which is not easy to process to plain text. Refer to Decoding data from WIN10 ssh server (response of paramiko recv()).

Solution

  • Paramiko SSHClient.invoke_shell opens "shell" SSH channel. What is basically only a shorthand for executing user's default shell. Otherwise it does not differ to what SSH "exec" channel (used by SSHClient.exec_command) does.

    Both "shell" and "exec" SSH channels can be started with or without the terminal emulation. It's only that Paramiko SSHClient.invoke_shell method does not offer that option (while SSHClient.exec_command does – via its get_pty parameter).

    There are two alternatives:

    • Use SSHClient.exec_channel to start the shell explicitly, like

      ssh.exec_command("/bin/bash")
      

      On Linux servers, you may even be able to avoid hard-coding the shell path by using the SHELL environment variable:

      ssh.exec_command("$SHELL")
      

      Similar might be done on Windows using %CMDSPEC% (untested).

    • Or re-implement SSHClient.invoke_shell to support execution without the terminal emulation.

      If you look at SSHClient.invoke_shell implementation, it does:

      chan = self._transport.open_session()
      chan.get_pty(term, width, height, width_pixels, height_pixels)
      chan.invoke_shell()
      

      All you need, is to do the same, just remove the Channel.get_pty call:

      chan = ssh.get_transport().open_session()
      chan.invoke_shell()
      

    Though note that there's a reason, why SSHClient.invoke_shell always uses the terminal emulation. The only purpose of SSH "shell" channel is implementing an interactive SSH terminal client (like PuTTY). A terminal client without the terminal emulation makes no sense.

    That you want to use "shell" channel without the terminal emulation indicates, that you are abusing it for purposes for which it was not designed. Think twice, if there's not a better solution to what you are trying to do!