2

I want to use the same SSH object to issue exec_command() multiple times in Paramiko module in Python.

The objective is to get output from the same session.

Is there a way to do it? The exec_command() closes channel once it completes executing a command and thereafter a new ssh object is needed to execute a following command .. but the sessions will differ which I do not want.

Code

import os, sys, 
import connectlibs as ssh
s = ssh.connect("xxx.xx.xx.xxx", "Admin", "Admin")
channel = s.invoke_shell()
channel.send("net use F: \\\\xyz.xy.xc.xa\\dir\n")
>>>32
channel.send("net use")
>>>7
channel.recv(500)
'Last login: Tue Jun  2 23:52:29 2015 from xxx.xx.xx.xx\r\r\n\x1b]0;~\x07\r\r\n\x1b[32mAdmin@WIN \x1b[33m~\x1b[0m\r\r\n$ net use F: \\\\xyz.xy.xc.xa\\dir\r\nSystem error 67 has occurred.\r\r\n\r\r\nThe network name cannot be found.\r\r\n\r\r\n\x1b]0;~\x07\r\r\n\x1b[32mAdmin@WIN \x1b[33m~\x1b[0m\r\r\n$ net use'
>>> 
Andrew T.
  • 4,701
  • 8
  • 43
  • 62
user2939055
  • 157
  • 1
  • 3
  • 14
  • You are confusing a "channel" and "session". What are you actually trying to do? What does *"get output from the same session"* mean? – Martin Prikryl Jun 03 '15 at 06:09
  • HI Martin: I want the outputs for the commands using the same "ssh object" - which means the same session. Session can have multiple channels - right? I want to send commands, one after the other and make sure that the output is OK. – user2939055 Jun 03 '15 at 06:11
  • For example, how could one execute the equivalent in python: pwd cd .. pwd – Lisle Nov 24 '16 at 05:55

1 Answers1

1

An SSH session can have multiple channels indeed (but Paramiko possibly does not support it).

But by a session you seem to imagine a "shell session". But that's not what the SSH session is. A channel is actually, what corresponds to a "shell session".

In other words, even if you could open multiple "exec" channels with Paramiko over the same SSH connection (session) and call the exec_command on these, the commands get executed in a different shell session. So it won't help you.


You can test this with PuTTY SSH client. The recent versions support connection sharing, what basically means that you can have more PuTTY windows (each using its own channel) over a single SSH connection/session. If you execute a command in one PuTTY window, and the commands changes an environment (like an environment variable or a current working directory), the change won't get reflected to the other PuTTY window, even if they share the same SSH connection.


So you need to execute the commands in one channel. Depending on your needs (which are still not clear), you need to use the "exec" or the "shell" channel.

In either case you will have troubles determining, where output of one command ends and output of other command starts as they share the same "stream".

You can solve that by inserting a unique separator (string) in between and search for it in the channel output stream.

channel = ssh.invoke_shell()
channel.send('ls\n')
channel.send('echo unique-string-separating-output-of-the-commands\n')
channel.send('pwd\n')
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • Yes, got both the links but the How do you execute multiple commands in a single session in Paramiko? (Python) -> does not work for me like the answer claims.It has not worked for some more people too from the comments. So how can I achieve this? How do I open a shell and execute? You mean, the "shell" is not using paramiko? – user2939055 Jun 03 '15 at 06:29
  • 1) *"Doesn't work for me"* is pretty vague. What comments do you refer to? I see only one. 2) *How do I open a shell and execute?* You do it as I've shown you in my answer, there's no other way. 3) *You mean, the "shell" is not using paramiko?* No idea what you mean. 4) If you tell is in more details, what you are trying to achieve, you may get better answers. – Martin Prikryl Jun 03 '15 at 06:33
  • 1
    I want to ssh into a system - use that "ssh_obj" to send commands A and B. After I execute command A, I want to parse its output and then execute B and then parse its output. I cant be on 2 different ssh sessions between A and B - which is why I am seeing if I can use the same "ssh_obj" to execute both, command A and B. – user2939055 Jun 03 '15 at 06:40
  • Ok- as per your code here, how do you get to parse the o/p of "ls"? – user2939055 Jun 03 '15 at 06:40
  • So your command A change/prepares the environment for command B somehow? Or why do you need to execute them in the same session? Ntb, you keep calling it SSH session, but you mean a shell session. Normally the difference is not important (as you have one shell session per SSH session). But in this case, when we talk about SSH channels, it's crucial. – Martin Prikryl Jun 03 '15 at 06:52
  • To explain what exactly I am doing: `code`"ssh_obj" is created; ch = ssh_obj.invoke_shell(); channel.send("net use J: \\\\xxx.xx.xx.xx\\share:) (OUTPUT:31);channel.recv_ready() (OUTPUT:True); channel.recv(200) (OUTPUT: Last login: Tue June 2 23:16:13 2015 from.......); channel.send("net use") (OUTPUT:7); channel.recv.ready() (OUTPUT:True); channel.recv(1000) (OUTPUT:'net use'); channel.recv(100) # this last one hangs `code`. Why cant I see the output of "net use J: \\.." which should be "Command sent successfully.." and output of "net use" which should be the mapping table. – user2939055 Jun 03 '15 at 06:59
  • Moreover, if I dont know exactly how many bytes are there in the response - say there are only 80 bytes in the actual response but I do "recv(900)" -> asking 900 bytes -- i will go in a looong hang.. I am not sure about this either. – user2939055 Jun 03 '15 at 07:09
  • Your comment is difficult to read. But you seem to miss the new line at the end of the command, see my code. – Martin Prikryl Jun 03 '15 at 07:09
  • There's no way to know the length of the response. You need to read it in a non-blocking manner. To detect an end of a command output, you need to use the trick outlined in my response. – Martin Prikryl Jun 03 '15 at 07:17
  • By trick if you mean "\n" - that did not help. I get get junk as part of my post above "Last login....junkkkk". Its still not clear 1. Why you keep sending and dont receive? 2. How exactly will I know how many bytes to receive (what if i dont know what message I am getting - success or failure or something else) 3. I called "channel.recv()" after each send. – user2939055 Jun 03 '15 at 07:35
  • 1) Such issue can hardly be resolved in comments. Consider asking a new question with sharing your complete code and results. I believe this question is answered. 2) Use the trick with a unique string from my answer. There's no better way, if you need to execute multiple commands in the same shell session. – Martin Prikryl Jun 03 '15 at 08:04