2

I'm trying to create a true interactive remote shell using Python. When I say true, I mean I don't want to just execute a single command and send the results- I have that working already. I also don't want to abstract executing single commands by having the server interpret directory changes or what not.

I am trying to have a client start an interactive /bin/bash and have the server send commands which are then executed by the same persistent shell. For instance, so if I run cd /foo/bar then pwd would return /foo/bar because I would be interacting with the same bash shell.

Here's some slimmed down example code that currently only will do single command execution...

# client.py
import socket
import subprocess
s = socket.socket()
s.connect(('localhost', 1337))
while True:
 cmd = s.recv(1024)
 # single command execution currently (not interactive shell)
 results = subprocess.Popen(cmd, shell=True,
 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
 stdin=subprocess.PIPE)
 results = results.stdout.read() + results.stderr.read()
 s.sendall(results)

# server.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 1337))
s.listen(5)
conn, _ = s.accept()
while True:
 cmd = raw_input('> ').rstrip()
 conn.send(cmd)
 results = conn.recv(4096)
 print results

I've tried many solutions none of which have worked. The subprocess module had a communication method, but it kills the shell after a single command. I'd really like to be able to accomplish this with stdlib, but I've looked at the pexpect module after reading this thread. However, I can't get that to work either? It also doesn't look like it's primary use case is for creating an interactive shell, but rather catching specific command line output for interaction. I can't even get single command execution working with pexpect...

import pexpect, sys
proc = pexpect.spawn('/bin/bash')
proc.logfile = sys.stdout
proc.expect('$ ')
proc.sendline('pwd\n')

If anyone can help it would be appreciated, I feel like there could be a way to multi-thread and spawn off a /bin/bash -i with subprocess and then some how write to stdin and read from stdout? Thanks in advance, and sorry for the length.

asked Mar 13, 2017 at 15:23
3
  • Why write all this yourself vs. using an ssh library, e.g. paramiko: see stackoverflow.com/questions/373639/… Commented Mar 13, 2017 at 15:27
  • @AChampion For this, you don't need to know the user's password. Commented Jun 8, 2017 at 20:36
  • Did you ever find a way to do this? Trying to do the same. Commented Jul 20, 2018 at 19:40

1 Answer 1

3

Try this code:

# client.py
import socket
import subprocess
s = socket.socket()
s.connect(('localhost', 1337))
process = subprocess.Popen(['/bin/bash', '-i'],
 stdout=s.makefile('wb'), stderr=subprocess.STDOUT,
 stdin=s.makefile('rb'))
process.wait()
# server.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 1337))
s.listen(5)
conn, _ = s.accept()
fp = conn.makefile('wb')
proc1 = subprocess.Popen('cat', stdin=conn.makefile('rb'))
while True:
 fp.write(sys.stdin.read(4096))
proc1.wait()
answered Sep 24, 2019 at 10:25
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.