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