I'm making a program with a remote shell utility in Python3, using sockets and subprocess. Everything works perfectly so far but i have encountered an issue i can't find the solution for. Here is the code on my server script which executes a command received from the client:
process = subprocess.Popen(client_buffer.decode('utf-8').split(), stdout = subprocess.PIPE) # Creating a process
while True: # Reading and sending the stdout from the process in realtime
shell_output = process.stdout.readline() # Read a line from stdout
return_code = process.poll()
print(shell_output)
print(return_code)
if shell_output.decode('utf-8') == '' and return_code is not None:
#print("Process execution complete. Sending user prefix")
send(client, ("<#" + color.user + getpass.getuser() + color.endc + "@" + color.dir + cwd() + color.endc + ">").encode('utf-8'))
break
elif shell_output:
# Process execution incomplete, signaling to client with code 2
send(client, int_to_bytes(2))
# And sending the next line of stdout
send(client, shell_output)
All works well and i was satisfied, but there is one limitation that i can't figure out how to remove. Namely, i can easily supply the server with a command with arguments and the server will execute it and send the output back, that works well, but if the program started by the command asks for additional input (for example a "(y/n)" question) before the execution of the process is over (mid-execution), i do not know how to supply the input to the process.
Can i do this with subprocess.Popen()? Any clue will be helpful and i thank You in advance. I forgot to add, the program is meant to be used in Linux.
PS Any functions and variables of which definitions/declarations i haven't provided in the code sample are irrelevant, but the project can be found on my github incase anyone wants to see more of the code
First I think readline()
is problematic here, unless the prompt from the program ends in a newline(): the program writes a prompt and is waiting for an answer while readline()
is waiting for an end-of-line. I think you're going to have to use read()
instead and do things a bit more low level.
To actually send something to the program, I think you can just write to process.stdin
.
Have a look at pexpect ( https://pexpect.readthedocs.io ). I'm not sure it fits your use case, but if it does it can make life easier so it's worth the effort to find out.
One other thing to consider: many commands have an option to make it work without extra prompts, to prevent the problem you're having when run from another program. If that's the case with the program you're using, that would be by far the easiest solution.
By providing the stdin
arg, you can access the subprocess'd processes' stdin
p = subprocess.Popen(
...
stdin=subprocess.PIPE,
...
)
p.stdin.write("foo")
You can also just send the input to myprocess.communicate()
, but it will then block until completion!
...
stdout, stderr = p.communicate(myinput)
You can send a large amount of inputs to answer many questions if you know what they will be in advance (such as a friendly "y\n" * 100
)
Well, first of all obvious and trivial mistake:
shell_output = process.stdout.readline()
NO.!! You can only write to the standard input and read from the standard input.
stdout = standard output
stdin = standard input
View piping as real pipes. The output flows in the input of the other command.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.