Example #1
0
    def _runcmd(self, args):
        env = {
            'PATH': os.environ.get('PATH'),
            'VORTEX_ENVIRONMENT': self.payload.environment,
        }

        if str(args) == args:
            # If we're asked to exec a simple string, we'll call a shell to do
            # the work.
            args = ['/bin/sh', '-c', args]

        if logger.isEnabledFor(logging.DEBUG):
            debug_env = ' '.join(
                "{var}={val}".format(
                    var=shell_quote(x), val=shell_quote(env[x]))
                for x in sorted(env))
            logger.debug("Running: env -i {env} {cmd}".format(
                env=debug_env, cmd=list_to_cmdline(args)))

        with open(os.devnull, 'r') as devnull:
            p = subprocess.Popen(
                args,
                stdin=devnull, stdout=None, stderr=None,
                close_fds=True, cwd=self.payload.directory, env=env)
            ret = p.wait()

        return ret
Example #2
0
def runcmd(args, env=None, cwd=None):
    """
    Simple wrapper around :class:`subprocess.Popen`.

    This is fairly similar to :func:`subprocess.call`, but makes certain
    assumptions and has other tweaks useful to Vortex:

    * Commands may only be run using an argument list. ``shell=True`` is
      deliberately not supported to avoid potential security problems. The
      `args` parameter must be a list.
    * The environment is always completely cleared except for the ``PATH`` and
      ``TERM`` environment variables. The `env` argument may be used to pass
      additional variables to the command being called.
    * The full command and any environment variables are sent to the logger at
      DEBUG log level to help the user diagnose any issues.
    * Standard input is always connected to ``/dev/null``.
    * Standard output and standard error are connected to the same pipe.

    This function returns a tuple consisting of (`returncode`, `output`), where
    `returncode` is the command's return code and `output` is the combination
    of the commands standard output and standard error.
    """
    if env is None:
        env = dict()

    # Copy in some basic environment variables from our environment, but
    # otherwise run with only the variables given.
    for var in ['PATH', 'TERM']:
        try:
            env.setdefault(var, os.environ[var])
        except KeyError:
            pass

    # Let's only do the work to print a nice string if a user is likely to see
    # it, otherwise it's just a waste of cycles.
    if logger.isEnabledFor(logging.DEBUG):
        debug_env = ' '.join(
            "{var}={val}".format(var=shell_quote(x), val=shell_quote(env[x]))
            for x in sorted(env))
        logger.debug("Running: env -i {env} {cmd}".format(
            env=debug_env, cmd=list_to_cmdline(args)))

    with open(os.devnull, 'r') as devnull:
        p = subprocess.Popen(
            args,
            stdin=devnull, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
            close_fds=True, cwd=cwd, env=env)
        output = p.communicate()[0]

    return (p.returncode, output)