Reputation: 491
I'm getting a command and arguments from the user, parsing them, and passing them to os.execvp()
, like so:
> ps -a -u -x
cmd = "ps"
args = ["-a", "-u", "-x"]
os.execvp(cmd, args)
The problem is that this doesn't work with pipes or redirects, so something like this wouldn't work:
> ps -a -u -x > output.txt
cmd = ps
args = ["-a", "-u", "-x", ">", "output.txt"]
os.execvp(cmd, args)
I understand that my problem is that >
and output.txt
are not arguments of ps
, I just don't know the best way to solve this problem. I'm hoping I'm just missing the right method.
Upvotes: 5
Views: 2442
Reputation: 17352
With os.execv
we are at the low level of the OS.
To redirect the output, we need to replace the file descriptor no. 1 (stdout) before executing the command.
import os
STDOUT = 1
fdout = os.open('output.txt', os.O_WRONLY)
os.dup2(fdout, STDOUT)
os.execvp('ps', 'ps -a -u -x'.split())
# not reached
os._exit(127) # just for the case of execv failure
More work is required to connect two processes with a pipe. The pipe has two ends and must be created first. Then fork
will duplicate the process. Each process must close one end of the pipe and redirect the other end to its stdin or stdout respectively.
import os
STDIN = 0
STDOUT = 1
pipein, pipeout = os.pipe()
if os.fork():
# parent
os.close(pipeout)
os.dup2(pipein, STDIN)
os.execlp('wc', '-l')
# not reached
os._exit(127)
else:
# child
os.close(pipein)
os.dup2(pipeout, STDOUT)
os.execvp('ps', 'ps -a -u -x'.split())
# not reached
os._exit(127)
These are just examples of concepts.
Upvotes: 5