On Fri, Mar 27, 2009 at 2:22 PM, James <rocketmonk...@gmail.com> wrote: > I've seen other posts about this, but no answers. My desire is to run > an SSH session in a scripted fashion. As one example, I would like to > be able to do this: > > client = paramiko.SSHClient() > client.connect(...) > client.exec_command('cd directory_name') > client.exec_command('ls') > > However, due to the way exec_command() works it automatically creates > a new session/channel every time. That means the results of the first > command (changing the working directory) does not affect the second > command (so the 'ls' wont give me the right directory listings). > > So the next step is to look at the transport & channel objects. Now I > have this: > > transport = client.get_transport() > session = transport.open_session() > session.exec_command('cd directory_name') > session.exec_command('ls') > > However, in this case I get an error because of this: > "When the command finishes executing, the channel will be closed and > can't be reused. You must open a new channel if you wish to execute > another command." > > I know I can do something like this: > client.exec_command('cd directory_name; ls') > > However, that means I cannot use the results of one command to > influence another. For example, if I wanted to 'ls file_name' to test > if a file existed, then do different things depending on if it was > there or not, I wouldn't be able to. >
Since you're running the command in a remote shell, you need to rely on that shell to handle some aspects of your program logic. Let the remote shell determine if the file exists, or whether the 'cd' was completed successfully. Tthe commands are being executed asynchronously, so you have no easy way to determine what's going on. Did the command complete with no output? Is it still running? > So my question is this: how do I execute multiple commands on a single > session/channel? I've seen others ask the same question, and so it > seems like there should be an obvious way to do this that I just don't > understand. > The best way to handle this is usually with exec_command, because then you *can* tell if the command is running, and it's exit status. Bundling the commands you want into small scripts may work well. > Please note: I do not want an interactive shell, unless that is the > preferred way for python to script commands in this scenario. I don't > want user input from the local computer (which is what I'm assuming > the invoke_shell() command is intended for). If you want a shell where you can send a command, read the result, and send another command, that is an interactive shell. To get a shell without a terminal, command prompt, login, etc; you could exec_command ' bash -s'. Then you could send commands over the channel, and read the output. In [5]: t = client.get_transport() In [6]: chan = t.open_session() In [7]: chan.exec_command('bash -s') In [8]: chan.send_ready() Out[8]: True In [9]: chan.send('pwd\n') Out[9]: 4 In [10]: chan.recv_ready() Out[10]: True In [11]: chan.recv(1024) Out[11]: '/home/jbardin\n' In [12]: chan.send('cd Desktop\n') Out[12]: 11 In [13]: chan.send_ready() Out[13]: True In [14]: chan.send('pwd\n') Out[14]: 4 In [15]: chan.recv_ready() Out[15]: True In [16]: chan.recv(1024) Out[16]: '/home/jbardin/Desktop\n' > I don't want to run 'cd > directory_name; ls; cmd; cmd; cmd;', since as I stated above that is > not sufficient for what I need. I would also like to avoid doing > adding 'ls directory_name' in front of every single command, since > that would also have to apply to things like environment variables, > etc. I'm truly looking for a way to execute multiple commands on a > single channel. > Because you're executing code on the remote machine, I highly recommend moving the logic there as well. There are also synchronous remote execution mechanisms like xmlrpc. You could always tunnel the xmlrpc socket over ssh for the security. -jim _______________________________________________ paramiko mailing list paramiko@lag.net http://www.lag.net/cgi-bin/mailman/listinfo/paramiko