Revision d5d76ab2 lib/utils/process.py
b/lib/utils/process.py | ||
---|---|---|
142 | 142 |
|
143 | 143 |
def RunCmd(cmd, env=None, output=None, cwd="/", reset_env=False, |
144 | 144 |
interactive=False, timeout=None, noclose_fds=None, |
145 |
_postfork_fn=None): |
|
145 |
input_fd=None, _postfork_fn=None):
|
|
146 | 146 |
"""Execute a (shell) command. |
147 | 147 |
|
148 | 148 |
The command should not read from its standard input, as it will be |
... | ... | |
170 | 170 |
@type noclose_fds: list |
171 | 171 |
@param noclose_fds: list of additional (fd >=3) file descriptors to leave |
172 | 172 |
open for the child process |
173 |
@type input_fd: C{file}-like object or numeric file descriptor |
|
174 |
@param input_fd: File descriptor for process' standard input |
|
173 | 175 |
@param _postfork_fn: Callback run after fork but before timeout (unittest) |
174 | 176 |
@rtype: L{RunResult} |
175 | 177 |
@return: RunResult instance |
... | ... | |
183 | 185 |
raise errors.ProgrammerError("Parameters 'output' and 'interactive' can" |
184 | 186 |
" not be provided at the same time") |
185 | 187 |
|
188 |
if not (output is None or input_fd is None): |
|
189 |
# The current logic in "_RunCmdFile", which is used when output is defined, |
|
190 |
# does not support input files (not hard to implement, though) |
|
191 |
raise errors.ProgrammerError("Parameters 'output' and 'input_fd' can" |
|
192 |
" not be used at the same time") |
|
193 |
|
|
186 | 194 |
if isinstance(cmd, basestring): |
187 | 195 |
strcmd = cmd |
188 | 196 |
shell = True |
... | ... | |
202 | 210 |
if output is None: |
203 | 211 |
out, err, status, timeout_action = _RunCmdPipe(cmd, cmd_env, shell, cwd, |
204 | 212 |
interactive, timeout, |
205 |
noclose_fds, |
|
213 |
noclose_fds, input_fd,
|
|
206 | 214 |
_postfork_fn=_postfork_fn) |
207 | 215 |
else: |
208 | 216 |
assert _postfork_fn is None, \ |
209 | 217 |
"_postfork_fn not supported if output provided" |
218 |
assert input_fd is None |
|
210 | 219 |
timeout_action = _TIMEOUT_NONE |
211 | 220 |
status = _RunCmdFile(cmd, cmd_env, shell, output, cwd, noclose_fds) |
212 | 221 |
out = err = "" |
... | ... | |
481 | 490 |
|
482 | 491 |
|
483 | 492 |
def _RunCmdPipe(cmd, env, via_shell, cwd, interactive, timeout, noclose_fds, |
493 |
input_fd, |
|
484 | 494 |
_linger_timeout=constants.CHILD_LINGER_TIMEOUT, |
485 | 495 |
_postfork_fn=None): |
486 | 496 |
"""Run a command and return its output. |
... | ... | |
500 | 510 |
@type noclose_fds: list |
501 | 511 |
@param noclose_fds: list of additional (fd >=3) file descriptors to leave |
502 | 512 |
open for the child process |
513 |
@type input_fd: C{file}-like object or numeric file descriptor |
|
514 |
@param input_fd: File descriptor for process' standard input |
|
503 | 515 |
@param _postfork_fn: Function run after fork but before timeout (unittest) |
504 | 516 |
@rtype: tuple |
505 | 517 |
@return: (out, err, status) |
... | ... | |
507 | 519 |
""" |
508 | 520 |
poller = select.poll() |
509 | 521 |
|
510 |
stderr = subprocess.PIPE |
|
511 |
stdout = subprocess.PIPE |
|
512 |
stdin = subprocess.PIPE |
|
513 |
|
|
514 | 522 |
if interactive: |
515 |
stderr = stdout = stdin = None |
|
523 |
stderr = None |
|
524 |
stdout = None |
|
525 |
else: |
|
526 |
stderr = subprocess.PIPE |
|
527 |
stdout = subprocess.PIPE |
|
528 |
|
|
529 |
if input_fd: |
|
530 |
stdin = input_fd |
|
531 |
elif interactive: |
|
532 |
stdin = None |
|
533 |
else: |
|
534 |
stdin = subprocess.PIPE |
|
516 | 535 |
|
517 | 536 |
if noclose_fds: |
518 | 537 |
preexec_fn = lambda: CloseFDs(noclose_fds) |
... | ... | |
549 | 568 |
|
550 | 569 |
timeout_action = _TIMEOUT_NONE |
551 | 570 |
|
571 |
# subprocess: "If the stdin argument is PIPE, this attribute is a file object |
|
572 |
# that provides input to the child process. Otherwise, it is None." |
|
573 |
assert (stdin == subprocess.PIPE) ^ (child.stdin is None), \ |
|
574 |
"subprocess' stdin did not behave as documented" |
|
575 |
|
|
552 | 576 |
if not interactive: |
553 |
child.stdin.close() |
|
577 |
if child.stdin is not None: |
|
578 |
child.stdin.close() |
|
554 | 579 |
poller.register(child.stdout, select.POLLIN) |
555 | 580 |
poller.register(child.stderr, select.POLLIN) |
556 | 581 |
fdmap = { |
Also available in: Unified diff