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()
|