Revision 7b0bf9cd lib/utils/process.py
b/lib/utils/process.py | ||
---|---|---|
141 | 141 |
|
142 | 142 |
|
143 | 143 |
def RunCmd(cmd, env=None, output=None, cwd="/", reset_env=False, |
144 |
interactive=False, timeout=None): |
|
144 |
interactive=False, timeout=None, noclose_fds=None):
|
|
145 | 145 |
"""Execute a (shell) command. |
146 | 146 |
|
147 | 147 |
The command should not read from its standard input, as it will be |
... | ... | |
166 | 166 |
@type timeout: int |
167 | 167 |
@param timeout: If not None, timeout in seconds until child process gets |
168 | 168 |
killed |
169 |
@type noclose_fds: list |
|
170 |
@param noclose_fds: list of additional (fd >=3) file descriptors to leave |
|
171 |
open for the child process |
|
169 | 172 |
@rtype: L{RunResult} |
170 | 173 |
@return: RunResult instance |
171 | 174 |
@raise errors.ProgrammerError: if we call this when forks are disabled |
... | ... | |
196 | 199 |
try: |
197 | 200 |
if output is None: |
198 | 201 |
out, err, status, timeout_action = _RunCmdPipe(cmd, cmd_env, shell, cwd, |
199 |
interactive, timeout) |
|
202 |
interactive, timeout, |
|
203 |
noclose_fds) |
|
200 | 204 |
else: |
201 | 205 |
timeout_action = _TIMEOUT_NONE |
202 |
status = _RunCmdFile(cmd, cmd_env, shell, output, cwd) |
|
206 |
status = _RunCmdFile(cmd, cmd_env, shell, output, cwd, noclose_fds)
|
|
203 | 207 |
out = err = "" |
204 | 208 |
except OSError, err: |
205 | 209 |
if err.errno == errno.ENOENT: |
... | ... | |
463 | 467 |
pass |
464 | 468 |
|
465 | 469 |
|
466 |
def _RunCmdPipe(cmd, env, via_shell, cwd, interactive, timeout, |
|
470 |
def _RunCmdPipe(cmd, env, via_shell, cwd, interactive, timeout, noclose_fds,
|
|
467 | 471 |
_linger_timeout=constants.CHILD_LINGER_TIMEOUT): |
468 | 472 |
"""Run a command and return its output. |
469 | 473 |
|
... | ... | |
479 | 483 |
@param interactive: Run command interactive (without piping) |
480 | 484 |
@type timeout: int |
481 | 485 |
@param timeout: Timeout after the programm gets terminated |
486 |
@type noclose_fds: list |
|
487 |
@param noclose_fds: list of additional (fd >=3) file descriptors to leave |
|
488 |
open for the child process |
|
482 | 489 |
@rtype: tuple |
483 | 490 |
@return: (out, err, status) |
484 | 491 |
|
... | ... | |
492 | 499 |
if interactive: |
493 | 500 |
stderr = stdout = stdin = None |
494 | 501 |
|
502 |
if noclose_fds: |
|
503 |
preexec_fn = lambda: CloseFDs(noclose_fds) |
|
504 |
close_fds = False |
|
505 |
else: |
|
506 |
preexec_fn = None |
|
507 |
close_fds = True |
|
508 |
|
|
495 | 509 |
child = subprocess.Popen(cmd, shell=via_shell, |
496 | 510 |
stderr=stderr, |
497 | 511 |
stdout=stdout, |
498 | 512 |
stdin=stdin, |
499 |
close_fds=True, env=env, |
|
500 |
cwd=cwd) |
|
513 |
close_fds=close_fds, env=env, |
|
514 |
cwd=cwd, |
|
515 |
preexec_fn=preexec_fn) |
|
501 | 516 |
|
502 | 517 |
out = StringIO() |
503 | 518 |
err = StringIO() |
... | ... | |
592 | 607 |
return out, err, status, timeout_action |
593 | 608 |
|
594 | 609 |
|
595 |
def _RunCmdFile(cmd, env, via_shell, output, cwd): |
|
610 |
def _RunCmdFile(cmd, env, via_shell, output, cwd, noclose_fds):
|
|
596 | 611 |
"""Run a command and save its output to a file. |
597 | 612 |
|
598 | 613 |
@type cmd: string or list |
... | ... | |
605 | 620 |
@param output: the filename in which to save the output |
606 | 621 |
@type cwd: string |
607 | 622 |
@param cwd: the working directory for the program |
623 |
@type noclose_fds: list |
|
624 |
@param noclose_fds: list of additional (fd >=3) file descriptors to leave |
|
625 |
open for the child process |
|
608 | 626 |
@rtype: int |
609 | 627 |
@return: the exit status |
610 | 628 |
|
611 | 629 |
""" |
612 | 630 |
fh = open(output, "a") |
631 |
|
|
632 |
if noclose_fds: |
|
633 |
preexec_fn = lambda: CloseFDs(noclose_fds + [fh.fileno()]) |
|
634 |
close_fds = False |
|
635 |
else: |
|
636 |
preexec_fn = None |
|
637 |
close_fds = True |
|
638 |
|
|
613 | 639 |
try: |
614 | 640 |
child = subprocess.Popen(cmd, shell=via_shell, |
615 | 641 |
stderr=subprocess.STDOUT, |
616 | 642 |
stdout=fh, |
617 | 643 |
stdin=subprocess.PIPE, |
618 |
close_fds=True, env=env, |
|
619 |
cwd=cwd) |
|
644 |
close_fds=close_fds, env=env, |
|
645 |
cwd=cwd, |
|
646 |
preexec_fn=preexec_fn) |
|
620 | 647 |
|
621 | 648 |
child.stdin.close() |
622 | 649 |
status = child.wait() |
Also available in: Unified diff