Home > Back-end >  How to capture stdout of shell after switching users
How to capture stdout of shell after switching users

Time:06-22

I'm making a shell with python. So far I have gotten cd to work (not pretty I know, but it's all I need for now). When I su root (for example) I get a root shell, but I can't capture the output I receive after running a command. However the shell does accept my commands, as when I type exit it exits. Is there a way to capture the output of a 'new' shell?

import os, subprocess

while True:
    command = input("$ ")
    if len(command.split(" ")) >= 2:
        print(command.split(" ")[0])  #This line is for debugging
        if command.split(" ")[0] == "cd" or command.split(" ")[1] == "cd":
            os.chdir(command.split(" ")[command.split(" ").index("cd")   1])
            continue
    process = subprocess.Popen(command.split(), stdout=subprocess.PIPE, universal_newlines=True)
    output, error = process.communicate()
    print(output.strip("\n"))

EDIT: To make my request a bit more precise, I'd like a way to authenticate as another user from a python script, basically catching the authentication, doing it in the background and then starting a new subprocess.

CodePudding user response:

You really need to understand how subprocess.Popen works. This command executes a new sub-process (on a Unix machine, calls fork and then exec). The new sub-process is a separate process. Your code just calls communicate once and then discards of it.

If you just create a new shell by calling subprocess.Popen and then running su <user> inside of it, the shell will be closed right after that and the next time, you'll be running the command using the same (original) user again.

What you want is probably to create a single subprocess at the beginning of your application and then be a sort of a proxy between the user and the underlying process, and then just keep writing to its stdin and reading from stdout.

Here's an example:

import os, subprocess

process = subprocess.Popen(["bash"], stdin=subprocess.PIPE,                                                                                                                                                               
    stdout=subprocess.PIPE, universal_newlines=True)

while True:
    command = input("$ ")
    process.stdin.write(command   "\n")
    process.stdin.flush()
    output = process.stdout.readline()
    print(output.strip("\n"))

(I removed the cd command parsing bit because it wasn't constructive to understanding the solution here, but you can definitely add specific handlers for specific inputs that wrap the underlying shell)

CodePudding user response:

I found a way to do so:

It seems like a dirty fix but it's works for me. After someone has su'd, I can add sudo -u <user> to the front of all their commands so it executes as them while remaining in the script.

  • Related