Пример #1
0
    def __init__(self, logger, cmd, cwd):
        """
          Start a subprocess for `cmd' in working directory `cwd'.

          Output is sent to `logger', or stdout if logger is None.
        """
        def print_logger(line):
            print(line)

        self.cmd = cmd
        self.killed = False
        self.completed = False
        self.logger = logger.info if logger else print_logger

        # report we are starting
        self.logger("Subprocess starting: %s (%s)" %
                    (" ".join(self.cmd), self.cmd))

        # start process
        self.process = subprocess.Popen(
            cmd,
            cwd=cwd,

            # Set buffering parameters
            bufsize=1,  # 1 = line buffering
            universal_newlines=True,  # translate ^M output by ssh -tt

            # Don't inherit our fds after fork()
            close_fds=True,

            # I/O redirection: block stdin, read stdout/stderr separately
            stdin=open("/dev/null"),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)
        self.pid = self.process.pid
        self.exit_status = None

        # output source streams
        self.output_streams = {
            self.STDOUT: self.process.stdout,
            self.STDERR: self.process.stderr
        }

        # output buffer
        self.output_buffers = {self.STDOUT: "", self.STDERR: ""}

        # output sink
        self.output_loggers = {
            self.STDOUT: logger.debug if logger else print_logger,
            self.STDERR: logger.warn if logger else print_logger
        }

        # Set fds to non-blocking to allow <4k reads. This is needed if the process
        # alternates between stdout and stderr output.
        for f in list(self.output_streams.values()):
            flag = fcntl.fcntl(f, fcntl.F_GETFL)
            fcntl.fcntl(f, fcntl.F_SETFL, flag | os.O_NONBLOCK)
Пример #2
0
def disk_usage(*paths):
    """
    Return the disk usage in bytes by the file(s) in ``paths``.
    """
    cmd = ['du', '-s', '-b']
    proc = subprocess.Popen(cmd + list(paths), stdout=subprocess.PIPE)
    sout = communicate_returning_strings(proc)[0]
    if sout:
        return sum([int(s.split('\t')[0]) for s in sout.strip().split('\n')])
    else:
        return 0
Пример #3
0
def spawn_process(cmd,
                  logger,
                  cwd=None,
                  env=None,
                  max_tries=2,
                  max_timeout=30):
    """
    DEPRECATED -- spawn_process leads to custom, and thus bad, output handling. Use
                  support.subprocessgroup.SubProcessGroup instead.

    Tries to spawn a process.

    If it hits an OSError due to lack of memory or too many open files, it
    will keep trying max_tries times, waiting timeout seconds between each.

    If successful, the process object is returned. Otherwise, we eventually
    propagate the exception.
    """

    logger.debug(
        "support.utilities.spawn_process is DEPRECATED. Please use support.subprocessgroup.SubProcessGroup"
    )

    # Make sure the working directory exists.
    create_directory(cwd)

    trycounter = 0
    while True:
        logger.debug("Spawning subprocess: cmd=%s, cwd=%s, env=%s" %
                     (cmd, cwd, env))
        try:
            process = subprocess.Popen(cmd,
                                       cwd=cwd,
                                       env=env,
                                       stdin=subprocess.PIPE,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)
        except OSError as e:
            logger.warn("Failed to spawn external process %s (%s)" %
                        (" ".join(cmd), str(e)))
            if trycounter < max_tries:
                timeout = randint(1, max_timeout)
                logger.warn("Retrying in %d seconds (%d more retries)." %
                            (timeout, max_tries - trycounter - 1))
                trycounter += 1
                time.sleep(timeout)
            else:
                raise
        else:
            break
    return process
Пример #4
0
def read_initscript(logger, filename, shell="/bin/sh"):
    """
    Return a dict of the environment after sourcing the given script in a shell.
    """
    if not os.path.exists(filename):
        logger.warn("Environment initialisation script not found!")
        return {}
    else:
        logger.debug("Reading environment from %s" % filename)
        p = subprocess.Popen(['. %s ; env' % (filename)],
                             shell=True,
                             executable=shell,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             close_fds=True)
        so, se = communicate_returning_strings(p)
        environment = [x.split('=', 1) for x in so.strip().split('\n')]
        environment = [x for x in environment if len(x) == 2]
        return dict(environment)
Пример #5
0
def spawn_process(cmd,
                  logger,
                  cwd=None,
                  env=None,
                  max_tries=2,
                  max_timeout=30):
    """
    Tries to spawn a process.

    If it hits an OSError due to lack of memory or too many open files, it
    will keep trying max_tries times, waiting timeout seconds between each.

    If successful, the process object is returned. Otherwise, we eventually
    propagate the exception.
    """
    trycounter = 0
    while True:
        logger.debug("Spawning subprocess: cmd=%s, cwd=%s, env=%s" %
                     (cmd, cwd, env))
        try:
            process = subprocess.Popen(cmd,
                                       cwd=cwd,
                                       env=env,
                                       stdin=subprocess.PIPE,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)
        except OSError, e:
            logger.warn("Failed to spawn external process %s (%s)" %
                        (" ".join(cmd), str(e)))
            if trycounter < max_tries:
                timeout = randint(1, max_timeout)
                logger.warn("Retrying in %d seconds (%d more retries)." %
                            (timeout, max_tries - trycounter - 1))
                trycounter += 1
                sleep(timeout)
            else:
                raise
        else:
            break