虽然对于大多数实现来说可能是“低级”的,但对于某些人来说,了解在更高级别的模块中这是如何发生的可能是很有教育意义的。在
import os
import pwd
pout, pin = os.pipe() # Creates an anonymous pipe used to communicate with the child process
if not os.fork(): # The fork() syscall duplicated the process retuning 0 to the new child process.
os.closerange(0, 2) # Closing stdin, stdout and stderr- they were inherited from the parent process
os.dup2(pin, 1) # Copy the input side of the IPC pipe to stdout (always fd 1)
os.setuid(pwd.getpwnam('nobody').pw_uid) # Change our user id to that of the user `nobody`. Also see `setgid()`
os.execl('/bin/whoami', 'whoami') # Now that we've connected out stdout to the pipe connected to the parent process
# and changed our user id to that of the user we want to run the command with
# we can `exec()` the new process; replacing our currently running process,
# inheriting the env.
os._exit(0) # Since we called `exec` above, this is never eval'd, but is good form
os.wait() # Back at the parent process- `wait()` will, well, wait until the child process exits.
os.close(pin) # Close the input side of the pipe, the parent shouldn't write to. (bi-dirctional IPC
# would require 2 pipes. One in each direction
child_stdout_pipe = os.fdopen(pout, 'r') # Open the output side of the IPC pipe
child_process_output = child_stdout_pipe.read() # ...and read from the pipe. This should include anything that came from the stdout of
# the child process. Since we closed the input side of the pipe, the `read()`
# will read an EOF after all the data in the pipe is returned.
print child_process_output # Win! (`write()`ing out the parent stdout want we found in the pipe from the child proc