def quote_and_substitute(self, tokens): ''' Quote each token to be suitable for shell expansion and then perform a substitution in the template. >>> from byexample.runner import ShebangTemplate >>> tokens = {'a': ['-i', "-c", 'blue = "1"'], ... 'e': '/usr/bin/env', 'p': 'python'} The basic case is a simple template where each token is quoted except the lists: each item is quoted but not the whole list as a single unit. >>> shebang = '%e %p %a' >>> print(ShebangTemplate(shebang).quote_and_substitute(tokens)) /usr/bin/env python -i -c 'blue = "1"' This works even if the token in the template are already quoted >>> shebang = '/bin/sh -c \'%e %p %a >/dev/null\'' >>> print(ShebangTemplate(shebang).quote_and_substitute(tokens)) /bin/sh -c '/usr/bin/env python -i -c '"'"'blue = "1"'"'"' >/dev/null' Here is another pair of examples: >>> tokens = {'a': ['-i', "-c", 'blue = \'1\''], ... 'e': '/usr/bin/env', 'p': 'py\'thon'} >>> shebang = '%e %p %a' >>> print(ShebangTemplate(shebang).quote_and_substitute(tokens)) /usr/bin/env 'py'"'"'thon' -i -c 'blue = '"'"'1'"'"'' >>> shebang = '/bin/sh -c \'%e %p %a >/dev/null\'' >>> print(ShebangTemplate(shebang).quote_and_substitute(tokens)) /bin/sh -c '/usr/bin/env '"'"'py'"'"'"'"'"'"'"'"'thon'"'"' -i -c '"'"'blue = '"'"'"'"'"'"'"'"'1'"'"'"'"'"'"'"'"''"'"' >/dev/null' ''' self._tokens = {} self._not_quote_them = [] for k, v in tokens.items(): if isinstance(v, (list, tuple)): self._tokens[k] = ' '.join(shlex_quote(i) for i in v) else: self._tokens[k] = shlex_quote(v) cmd = [] for x in shlex.split(self.template): # *before* the expansion, will this require quote? (will yield # more than a single item?) should_quote = len(shlex.split(x)) > 1 # perform the expansion x = ShebangTemplate(x).substitute(self._tokens) # was needed to quote this *before* the expansion? if should_quote: x = shlex_quote(x) cmd.append(x) return ' '.join(cmd)
def execute(self, *, blocking=False, debug=False, silent=False, **kwargs): from tempfile import mkstemp import stat from shlex import quote as shlex_quote tf = mkstemp(suffix=".sh", prefix="bashf-")[1] with open(tf, "w") as f: f.write(self.source) # Mark the temporary file as executable. st = os.stat(tf) os.chmod(tf, st.st_mode | stat.S_IEXEC) stdlib_path = os.path.join(os.path.dirname(__file__), "scripts", "stdlib.sh") args = [shlex_quote(a) for a in self.bashfile.args] if silent: script = shlex_quote(f"{tf} {args}") else: script = shlex_quote(f"{tf} {args} 2>&1 | bake-indent") cmd = f"bash --init-file {shlex_quote(stdlib_path)} -i -c {script} " if debug: print(cmd) return os.system(cmd)
def build_httpie_command(request): parts = ['http'] redir_input = '' # Method if request.command != 'GET': parts.append(request.command) # URL parts.append(shlex_quote(request.url())) # Authorization (prepare) method, token = request.auth() # Headers for header in sorted(request.headers): if header in EXCLUDE_HEADERS_HTTP: continue parts.append('{}:{}'.format(header, shlex_quote( request.headers[header]))) # noqa if method != 'Basic' and 'Authorization' in request.headers: header = 'Authorization' parts.append('{}:{}'.format(header, shlex_quote( request.headers[header]))) # noqa # JSON or raw data data = maybe_str(request.data()) if data: content_type = request.headers.get('Content-Type', '') if is_json(content_type): # We need to explicitly set the separators to get consistent # whitespace handling across Python 2 and 3. See # https://bugs.python.org/issue16333 for details. redir_input = shlex_quote( json.dumps(data, indent=2, sort_keys=True, separators=(',', ': '))) elif is_form(content_type): parts[0] += ' --form' parts.append(data.replace('\n', ' ')) else: redir_input = shlex_quote(data) # Authorization if method == 'Basic': parts.append('-a {}'.format(token)) cmd = ' '.join(parts) if not redir_input: return cmd else: return 'echo {} | {}'.format(redir_input, cmd)
def _put_file(self, src_path, dest_path): dest_path = self._prepare_dest_path(src_path, dest_path, local=False, absolute_only=True) cmd = 'cat {} | singularity exec instance://{} tee {} > /dev/null' self._runner.run( cmd.format(shlex_quote(src_path), self.name, shlex_quote(dest_path)))
def get(self, src_path, dest_path=None, uid=-1, gid=-1): dest_path = self._prepare_dest_path(src_path, dest_path) cmd = 'singularity exec instance://{} cat {} > {}' self._runner.run( cmd.format(self.name, shlex_quote(src_path), shlex_quote(dest_path))) if uid > -1 or gid > -1: self.chown(dest_path, uid, gid, remote=False)
def command_line(self) -> str: command_line = shlex_quote(str(self.command)) if self.args: command_line += " " + " ".join( (shlex_quote(str(arg)) for arg in self.args)) descriptors = self.descriptors.command_line if len(descriptors) > 0: command_line += " " + descriptors return command_line
def put(self, src_path, dest_path, uid=-1, gid=-1): dest_path = self._prepare_dest_path(src_path, dest_path, local=False, absolute_only=True) cmd = 'cat {} | singularity exec instance://{} tee {} > /dev/null' self._runner.run( cmd.format(shlex_quote(src_path), self.name, shlex_quote(dest_path))) if uid > -1 or gid > -1: self.chown(dest_path, uid, gid)
def new_cmd(session, name, cmd, mode, logdir, shell): if isinstance(cmd, (list, tuple)): cmd = " ".join(shlex_quote(str(v)) for v in cmd) if mode == 'tmux': return name, "tmux send-keys -t {}:{} {} Enter".format( session, name, shlex_quote(cmd)) elif mode == 'child': return name, "{} >{}/{}.{}.out 2>&1 & echo kill $! >>{}/kill.sh".format( cmd, logdir, session, name, logdir) elif mode == 'nohup': return name, "nohup {} -c {} >{}/{}.{}.out 2>&1 & echo kill $! >>{}/kill.sh".format( shell, shlex_quote(cmd), logdir, session, name, logdir)
def _set_serial(self, netloc, port): """ set serial from openssl :param netloc: target netloc :param port: target port :return: """ with sp_Popen([self.echo_cmd], stdout=SP_PIPE) as proc_echo: cmd = self.ssl_client_cmd[:] cmd.append('{}:{}'.format(shlex_quote(netloc), str(port))) with sp_Popen(cmd, stdin=proc_echo.stdout, stdout=SP_PIPE, stderr=SP_DEVNULL) as proc_ssl: cmd = self.ssl_x509_cmd[:] cmd.append('-noout') cmd.append('-serial') with sp_Popen(cmd, stdin=proc_ssl.stdout, stdout=SP_PIPE, stderr=SP_DEVNULL) as proc_x509: data = proc_x509.stdout.read() ddata = data.decode('utf-8') if ddata is not None: reg = re_compile('serial=([^\n]+)') res = reg.search(ddata) if res is not None: self.serialNumber = res.group(1)
def _set_dates(self, netloc, port): """ set dates from openssl (notAfter and not Before) :param netloc: target netloc :param port: target port :return: """ with sp_Popen([self.echo_cmd], stdout=SP_PIPE) as proc_echo: cmd = self.ssl_client_cmd[:] cmd.append('{}:{}'.format(shlex_quote(netloc), str(port))) with sp_Popen(cmd, stdin=proc_echo.stdout, stdout=SP_PIPE, stderr=SP_DEVNULL) as proc_ssl: cmd = self.ssl_x509_cmd[:] cmd.append('-noout') cmd.append('-dates') with sp_Popen(cmd, stdin=proc_ssl.stdout, stdout=SP_PIPE, stderr=SP_DEVNULL) as proc_x509: data = proc_x509.stdout.read() ddata = data.decode('utf-8') if ddata is not None: reg = re_compile('notBefore=([^\n]+)') res = reg.search(ddata) if res is not None: self.notBefore = datetime.fromtimestamp( cert_time_to_seconds(res.group(1))) reg = re_compile('notAfter=([^\n]+)') res = reg.search(ddata) if res is not None: self.notAfter = datetime.fromtimestamp( cert_time_to_seconds(res.group(1)))
def _set_issuer(self, netloc, port): """ set issuer dict from openssl :param netloc: target netloc :param port: target port :return: """ with sp_Popen([self.echo_cmd], stdout=SP_PIPE) as proc_echo: cmd = self.ssl_client_cmd[:] cmd.append('{}:{}'.format(shlex_quote(netloc), str(port))) with sp_Popen(cmd, stdin=proc_echo.stdout, stdout=SP_PIPE, stderr=SP_DEVNULL) as proc_ssl: cmd = self.ssl_x509_cmd[:] cmd.append('-noout') cmd.append('-issuer') with sp_Popen(cmd, stdin=proc_ssl.stdout, stdout=SP_PIPE, stderr=SP_DEVNULL) as proc_x509: data = proc_x509.stdout.read() ddata = data.decode('utf-8') if ddata is not None: issuer_dict = dict() reg = re_compile('[A-Z]+=[^/\n]+') for res in reg.finditer(ddata): _split = res.group().split('=') if str(_split[0]) in self.keys: issuer_dict[self.keys[str( _split[0])]] = _split[1] self.issuer = issuer_dict
def _set_error_message(self, netloc, port): """ set basic error from openssl (certificate not valid) :param netloc: target netloc :param port: target port :return: """ with sp_Popen([self.echo_cmd], stdout=SP_PIPE) as proc_echo: cmd = self.ssl_client_cmd[:] cmd.append('{}:{}'.format(shlex_quote(netloc), str(port))) cmd.append('-CAfile') cmd.append(CA_CERTS) with sp_Popen(cmd, stdin=proc_echo.stdout, stdout=SP_DEVNULL, stderr=SP_PIPE) as proc_ssl: data = proc_ssl.stderr.read() ddata = data.decode('utf-8') if ddata is not None: reg = re_compile('error:num=[0-9]+:([^\n]+)') for res in reg.finditer(ddata): # expired checked at the end # print('error msg: {}'.format(res.group(0))) if 'expired' not in res.group(1): self.add_error(err=NameError(res.group(1)))
def _run_one_hook(event, executable, *args): try: devnull = subprocess.DEVNULL except AttributeError: # python 2.x devnull = open(os.devnull, 'w') call_args = [shlex_quote(str(arg)) for arg in args] call_args.insert(0, executable) argstr = ' '.join(call_args) log.debug('Run hook: {s!r}'.format(s=argstr)) exit_code = subprocess.call( argstr, shell=True, stdout=devnull, stderr=devnull, ) name = os.path.basename(executable) if exit_code == 0: log.debug(('Successfully ran hook {!r}' ' on event {!r}.').format(name, event)) else: log.error(('Hook {!r} exited with non-zero exit status ({})' ' on event {!r}.').format(name, exit_code, event))
def getcommandpath(self, name, venv=True, cwd=None): """Return absolute path (str or localpath) for specified command name. - If it's a local path we will rewrite it as as a relative path. - If venv is True we will check if the command is coming from the venv or is allowed to come from external. """ name = str(name) if os.path.isabs(name): return name if os.path.split(name)[0] == ".": path = cwd.join(name) if path.check(): return str(path) if venv: path = self._venv_lookup_and_check_external_allowlist(name) else: path = self._normal_lookup(name) if path is None: raise tox.exception.InvocationError( "could not find executable {}".format(shlex_quote(name)), ) return str(path) # will not be rewritten for reporting
def _low_level_execute_command(self, cmd, sudoable=True, in_data=None, executable=None, encoding_errors='surrogate_then_replace', chdir=None): """ Override the base implementation by simply calling target.exec_command() in the target context. """ LOG.debug('_low_level_execute_command(%r, in_data=%r, exe=%r, dir=%r)', cmd, type(in_data), executable, chdir) if executable is None: # executable defaults to False executable = self._play_context.executable if executable: cmd = executable + ' -c ' + shlex_quote(cmd) rc, stdout, stderr = self._connection.exec_command( cmd=cmd, in_data=in_data, sudoable=sudoable, mitogen_chdir=chdir, ) stdout_text = to_text(stdout, errors=encoding_errors) return { 'rc': rc, 'stdout': stdout_text, 'stdout_lines': stdout_text.splitlines(), 'stderr': stderr, }
def tclscan(filename: str) -> dict: """tclscan executes tclscan in a subprocess. It expects filename as str and returns a dict with errors, warnings and dangerous as lists. """ results: dict = {"errors": [], "warnings": [], "dangerous": []} result = subprocess.run( ["tclscan", "check", shlex_quote(filename)], capture_output=True ) try: result.check_returncode() except subprocess.CalledProcessError: err: str = "ERROR: cannot scan, manual code verification required, error: " err += result.stderr.decode("utf8") results["errors"].append(err) return results res = result.stdout.replace(b"\\\n", b"") res = res.decode("utf8") for line in res.splitlines(False): if not line: continue elif line.startswith("WARNING: message:badly formed command"): # badly formed commands stop the scan, hence error instead of warning results["errors"].append(line.replace("WARNING: message:", "")) elif line.startswith("DANGEROUS:"): results["dangerous"].append(line.replace("DANGEROUS: message:", "")) elif line.startswith("WARNING:"): results["warnings"].append(line.replace("WARNING: message:", "")) else: results["errors"].append(line[0:1024]) return results
def get_boot_command(self): bits = [self.ssh_path] # bits += ['-o', 'BatchMode yes'] if self.username: bits += ['-l', self.username] if self.port is not None: bits += ['-p', str(self.port)] if self.identity_file or self.password: bits += ['-o', 'IdentitiesOnly yes'] if self.identity_file: bits += ['-i', self.identity_file] if self.compression: bits += ['-o', 'Compression yes'] if self.keepalive_enabled: bits += [ '-o', 'ServerAliveInterval %s' % (self.keepalive_interval,), '-o', 'ServerAliveCountMax %s' % (self.keepalive_count,), ] if not self.check_host_keys: bits += [ '-o', 'StrictHostKeyChecking no', '-o', 'UserKnownHostsFile /dev/null', '-o', 'GlobalKnownHostsFile /dev/null', ] if self.ssh_args: bits += self.ssh_args bits.append(self.hostname) base = super(Stream, self).get_boot_command() return bits + [shlex_quote(s).strip() for s in base]
def execute(self, *, blocking=False, debug=False, silent=False, **kwargs): init_tf = self.prepare_init() if self.bashfile._is_shebang_line(self.source_lines[0]): script_tf = self.prepare_init(sources=[self.source]) if self.source_lines[0] == "#!/usr/bin/env bash": with open(script_tf, "r") as f: lines = f.readlines() lines.insert(1, f"source {init_tf}") with open(script_tf, "w") as f: f.write("\n".join(lines)) else: script_tf = self.prepare_init(sources=[self.source], insert_source=init_tf) args = " ".join([shlex_quote(a) for a in self.bashfile.args]) script = f"source {shlex_quote(init_tf)}; {shlex_quote(script_tf)} {args} | bake:indent" cmd = f"bash -c {shlex_quote(script)}" if debug: click.echo(f" $ {cmd}", err=True) c = os.system(cmd) if not debug: os.remove(script_tf) os.remove(init_tf) return c
def test_command_prev_fail_command_skip_post_run(cmd, initproj, mock_venv): initproj( "pkg_command_test_123-0.7", filedefs={ "tox.ini": """ [tox] envlist = py [testenv] commands_pre = python -c 'raise SystemExit(2)' commands = python -c 'print("command")' commands_post = python -c 'print("post")' """, }, ) result = cmd() result.assert_fail() expected = textwrap.dedent( """ py run-test-pre: commands[0] | python -c 'raise SystemExit(2)' ERROR: InvocationError for command {} -c 'raise SystemExit(2)' (exited with code 2) py run-test-post: commands[0] | python -c 'print("post")' post ___________________________________ summary ___________________________________{} ERROR: py: commands failed """.format( shlex_quote(sys.executable), "_" if sys.platform != "win32" else "", ), ) have = result.out.replace(os.linesep, "\n") actual = have[len(have) - len(expected):] assert actual == expected
def command(self, script: str, debug=False, **kwargs) -> BashProcess: """form up the command with shlex and execute""" tf = mkstemp(suffix=".sh", prefix="bashf-")[1] with open(tf, "w") as f: f.write(script) # Mark the temporary file as executable. st = os.stat(tf) os.chmod(tf, st.st_mode | stat.S_IEXEC) stdlib_path = os.path.join(os.path.dirname(__file__), "scripts", "stdlib.sh") # print(stdlib_path) # cmd = f"bash -c {(script)}" script = shlex_quote(f"unbuffer {tf} 2>&1 | bashf-indent") cmd = f"bash --init-file {shlex_quote(stdlib_path)} -i -c {script} " if debug: print(cmd) return_code = os.system(cmd) if not debug: # Cleanup temporary file. os.remove(tf) return return_code
def _get_args_contents(self): """ Mimic the argument formatting behaviour of ActionBase._execute_module(). """ return ' '.join('%s=%s' % (key, shlex_quote(str(self.args[key]))) for key in self.args) + ' ' # Bug-for-bug :(
def _low_level_execute_command(self, cmd, sudoable=True, in_data=None, executable=None, encoding_errors='surrogate_then_replace', chdir=None): """ Override the base implementation by simply calling target.exec_command() in the target context. """ LOG.debug('_low_level_execute_command(%r, in_data=%r, exe=%r, dir=%r)', cmd, type(in_data), executable, chdir) if executable is None: # executable defaults to False executable = self._play_context.executable if executable: cmd = executable + ' -c ' + shlex_quote(cmd) rc, stdout, stderr = self._connection.exec_command( cmd=cmd, in_data=in_data, sudoable=sudoable, mitogen_chdir=chdir, ) stdout_text = to_text(stdout, errors=encoding_errors) return { 'rc': rc, 'stdout': stdout_text, 'stdout_lines': stdout_text.splitlines(), 'stderr': stderr, }
def execute(self, *, blocking=False, debug=False, interactive=False, silent=False, **kwargs): args = " ".join([shlex_quote(a) for a in self.bf.args]) args = args if args else "\b" sed_magic = ("2>&1 | sed >&2 's/^/ | /'" if not (silent or interactive) else "\b") script = (f"t=$(mktemp) && bake --source {self.name} " "> ${t} && chmod +x ${t} && ${t} " + f"{args} " + f"{sed_magic} " + '&& EXIT="${PIPESTATUS[0]}" ' "&& rm -fr ${t} && exit ${EXIT}") if debug: click.echo(f" {click.style('$', fg='green')} {script}", err=True) if silent: bash_interactive = True else: bash_interactive = interactive bash = Bash(interactive=bash_interactive) return bash.command(script, quote=False)
def _run_pip_command(self, *args): """ Use a shell-escaped version of sys.executable with pip module :param args: pip args :return: the command result """ return subprocess.check_output([shlex_quote(sys.executable), "-m", "pip"] + list(*args), stderr=subprocess.DEVNULL).decode().strip()
def call(args, env=None, cwd=None, shell=False): # print the command executing for the logs if shell: print('+ %s' % args) else: print('+ ' + ' '.join(shlex_quote(a) for a in args)) return subprocess.check_call(args, env=env, cwd=cwd, shell=shell)
def main(opt): # these are all very, very bad. subprocess.call(opt, shell=True) subprocess.run(opt, shell=True) subprocess.Popen(opt, shell=True) # this is less-bad because its being escaped, but bandit doesnt care subprocess.call(shlex_quote(opt), shell=True)
def _run_git_command(self, *args): """ Use a shell-escaped version of git executable :param args: git args :return: the command result """ return subprocess.check_output([shlex_quote("git")] + list(*args), stderr=subprocess.DEVNULL).decode().strip()
def build_wget_command(request): parts = ['wget', '-S', '-O-'] # Method if request.command not in ['GET', 'POST']: parts.append('--method={}'.format(request.command)) # URL parts.append(shlex_quote(request.url())) # Authorization (prepare) method, token = request.auth() # Headers for header in sorted(request.headers): if header in EXCLUDE_HEADERS: continue header_line = shlex_quote('{}: {}'.format( header, request.headers[header])) # noqa: E501 parts.append('--header={}'.format(header_line)) if method != 'Basic' and 'Authorization' in request.headers: header = 'Authorization' header_line = shlex_quote('{}: {}'.format( header, request.headers[header])) # noqa: E501 parts.append('--header={}'.format(header_line)) # JSON or raw data data = maybe_str(request.data()) if data: if is_json(request.headers.get('Content-Type', '')): data = json.dumps(data) if request.command == 'POST': parts.append('--post-data=\'{}\''.format(data)) elif request.command != 'POST': parts.append('--body-data=\'{}\''.format(data)) # Authorization if method == 'Basic': user, password = token.split(':') parts.append('--auth-no-challenge') parts.append('--user={}'.format(user)) parts.append('--password={}'.format(password)) return ' '.join(parts)
def _get_args_contents(self): """ Mimic the argument formatting behaviour of ActionBase._execute_module(). """ return ' '.join( '%s=%s' % (key, shlex_quote(str(self.args[key]))) for key in self.args ) + ' ' # Bug-for-bug :(
def shell_cmd(cmd: Sequence[str]) -> str: if sys.platform.startswith("win"): from subprocess import list2cmdline return list2cmdline(tuple(str(x) for x in cmd)) else: from shlex import quote as shlex_quote return " ".join(shlex_quote(str(x)) for x in cmd)
def _run_command(self, command): # TODO: On Windows, fall back to CMD.exe if SHELL is not defined. command = [os.environ['SHELL'], '-c', command] print('$', ' '.join(shlex_quote(x) for x in command)) try: return subprocess.call(command) except (OSError, IOError) as exc: print('Error: can not run "{}" ({})'.format(cmd, exc)) return getattr(exc, 'errno', 127)
def test_cplusplus(self): with open('generator.cpp', 'w') as fh: fh.write(generator_cpp) self.system('g++ -std=c++11 generator.cpp') self.system('./a.out | head -n 1000 > data.txt') self.system('head -n 624 data.txt > known.txt') self.system('tail -n 376 data.txt > correct.txt') self.system(shlex_quote(self.original_dir + '/bin/mt19937predict') + ' known.txt | head -n 376 > predicted.txt') # this uses an installed script in system self.system('diff predicted.txt correct.txt')
def _prefix_command(self, command, env=None, cwd=None, with_shell=False): """Wrap the command in a shell call with ENV vars and CWD prefixed statment to command. Will pass through the command unchanged if env and cwd are None Parameters ---------- command : string or list Shell command to be run. No shell is used if command is a list env : dict ENV vars to prefix to command cwd : string Working directory to cd into before the command is executed with_shell : boolean if True and command is a string, a "/bin/sh -c" call will wrap the cwd, env and command Returns ------- string or list command with env, cwd, and/or with_shell settings prefixed """ prefix = [] if env: prefix = ["export"] prefix += [ "{}={}".format(shlex_quote(k[0]), shlex_quote(k[1])) for k in env.items() ] prefix += ["&&"] if cwd: prefix += ["cd", cwd, "&&"] if with_shell and isinstance(command, str): if prefix: cmd = "{} {}".format(" ".join(prefix), command) else: cmd = "{}".format(command) command = "/bin/sh -c '{}'".format(cmd) elif prefix: if isinstance(command, str): command = " ".join(prefix) + " " + command else: command = prefix + command return command
def _get_shell_fragment(self): """ Scripts are eligible for having their hashbang line rewritten, and to be executed via /bin/sh using the ansible_*_interpreter value used as a shell fragment prefixing to the invocation. """ return "%s %s %s" % ( self.interpreter_fragment, shlex_quote(self.program_fp.name), ' '.join(map(shlex_quote, self._get_program_args())), )
def build(self): '''Render reStructuredText files with sphinx''' started = time.time() logger.info('Building...') result = run( 'sphinx-build {rst_path} {output_path}'.format( rst_path=shlex_quote(self.c.sphinx_path), output_path=shlex_quote( os.path.join(self.c.sphinx_path, self.c.output) ) ) ) if result.stderr.strip(): logger.warning(result.stderr.strip()) total_seconds = time.time() - started logger.info('Build completed in %fs', total_seconds) return result
def get_boot_command(self): bits = [self.ssh_path] if self.ssh_debug_level: bits += ['-' + ('v' * min(3, self.ssh_debug_level))] else: # issue #307: suppress any login banner, as it may contain the # password prompt, and there is no robust way to tell the # difference. bits += ['-o', 'LogLevel ERROR'] if self.username: bits += ['-l', self.username] if self.port is not None: bits += ['-p', str(self.port)] if self.identities_only and (self.identity_file or self.password): bits += ['-o', 'IdentitiesOnly yes'] if self.identity_file: bits += ['-i', self.identity_file] if self.compression: bits += ['-o', 'Compression yes'] if self.keepalive_enabled: bits += [ '-o', 'ServerAliveInterval %s' % (self.keepalive_interval,), '-o', 'ServerAliveCountMax %s' % (self.keepalive_count,), ] if not self._requires_pty(): bits += ['-o', 'BatchMode yes'] if self.check_host_keys == 'enforce': bits += ['-o', 'StrictHostKeyChecking yes'] if self.check_host_keys == 'accept': bits += ['-o', 'StrictHostKeyChecking ask'] elif self.check_host_keys == 'ignore': bits += [ '-o', 'StrictHostKeyChecking no', '-o', 'UserKnownHostsFile /dev/null', '-o', 'GlobalKnownHostsFile /dev/null', ] if self.ssh_args: bits += self.ssh_args bits.append(self.hostname) base = super(Stream, self).get_boot_command() return bits + [shlex_quote(s).strip() for s in base]
def subst(self, command, var_name, value): """Replace all occurrences of `var_name` in `command` with `value`, but make sure `value` is properly shell-escaped first.""" return command.replace(var_name, shlex_quote(value))
def files_up_to_date(files, test): for fname, value in files.iteritems(): if test(fname) != value: logging.debug("Not up to date: %s", shlex_quote(fname)) return False return True
def main(): module = AnsibleModule( argument_spec = dict( src = dict(required=True), dest = dict(required=True), dest_port = dict(default=None, type='int'), delete = dict(default='no', type='bool'), private_key = dict(default=None), rsync_path = dict(default=None), _local_rsync_path = dict(default='rsync', type='path'), _substitute_controller = dict(default='no', type='bool'), archive = dict(default='yes', type='bool'), checksum = dict(default='no', type='bool'), compress = dict(default='yes', type='bool'), existing_only = dict(default='no', type='bool'), dirs = dict(default='no', type='bool'), recursive = dict(type='bool'), links = dict(type='bool'), copy_links = dict(default='no', type='bool'), perms = dict(type='bool'), times = dict(type='bool'), owner = dict(type='bool'), group = dict(type='bool'), set_remote_user = dict(default='yes', type='bool'), rsync_timeout = dict(type='int', default=0), rsync_opts = dict(type='list'), ssh_args = dict(type='str'), partial = dict(default='no', type='bool'), verify_host = dict(default='no', type='bool'), mode = dict(default='push', choices=['push', 'pull']), ), supports_check_mode = True ) if module.params['_substitute_controller']: try: source = substitute_controller(module.params['src']) dest = substitute_controller(module.params['dest']) except ValueError: module.fail_json(msg='Could not determine controller hostname for rsync to send to') else: source = module.params['src'] dest = module.params['dest'] dest_port = module.params['dest_port'] delete = module.params['delete'] private_key = module.params['private_key'] rsync_path = module.params['rsync_path'] rsync = module.params.get('_local_rsync_path', 'rsync') rsync_timeout = module.params.get('rsync_timeout', 'rsync_timeout') archive = module.params['archive'] checksum = module.params['checksum'] compress = module.params['compress'] existing_only = module.params['existing_only'] dirs = module.params['dirs'] partial = module.params['partial'] # the default of these params depends on the value of archive recursive = module.params['recursive'] links = module.params['links'] copy_links = module.params['copy_links'] perms = module.params['perms'] times = module.params['times'] owner = module.params['owner'] group = module.params['group'] rsync_opts = module.params['rsync_opts'] ssh_args = module.params['ssh_args'] verify_host = module.params['verify_host'] if '/' not in rsync: rsync = module.get_bin_path(rsync, required=True) cmd = [rsync, '--delay-updates', '-F'] if compress: cmd.append('--compress') if rsync_timeout: cmd.append('--timeout=%s' % rsync_timeout) if module.check_mode: cmd.append('--dry-run') if delete: cmd.append('--delete-after') if existing_only: cmd.append('--existing') if checksum: cmd.append('--checksum') if copy_links: cmd.append('--copy-links') if archive: cmd.append('--archive') if recursive is False: cmd.append('--no-recursive') if links is False: cmd.append('--no-links') if perms is False: cmd.append('--no-perms') if times is False: cmd.append('--no-times') if owner is False: cmd.append('--no-owner') if group is False: cmd.append('--no-group') else: if recursive is True: cmd.append('--recursive') if links is True: cmd.append('--links') if perms is True: cmd.append('--perms') if times is True: cmd.append('--times') if owner is True: cmd.append('--owner') if group is True: cmd.append('--group') if dirs: cmd.append('--dirs') if source.startswith('rsync://') and dest.startswith('rsync://'): module.fail_json(msg='either src or dest must be a localhost', rc=1) if is_rsh_needed(source, dest): ssh_cmd = [module.get_bin_path('ssh', required=True), '-S', 'none'] if private_key is not None: ssh_cmd.extend(['-i', os.path.expanduser(private_key) ]) # If the user specified a port value # Note: The action plugin takes care of setting this to a port from # inventory if the user didn't specify an explicit dest_port if dest_port is not None: ssh_cmd.extend(['-o', 'Port=%s' % dest_port]) if not verify_host: ssh_cmd.extend(['-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null']) ssh_cmd_str = ' '.join(shlex_quote(arg) for arg in ssh_cmd) if ssh_args: ssh_cmd_str += ' %s' % ssh_args cmd.append('--rsh=%s' % ssh_cmd_str) if rsync_path: cmd.append('--rsync-path=%s' % rsync_path) if rsync_opts: cmd.extend(rsync_opts) if partial: cmd.append('--partial') changed_marker = '<<CHANGED>>' cmd.append('--out-format=' + changed_marker + '%i %n%L') # expand the paths if '@' not in source: source = os.path.expanduser(source) if '@' not in dest: dest = os.path.expanduser(dest) cmd.append(source) cmd.append(dest) cmdstr = ' '.join(cmd) (rc, out, err) = module.run_command(cmd) if rc: return module.fail_json(msg=err, rc=rc, cmd=cmdstr) else: changed = changed_marker in out out_clean = out.replace(changed_marker, '') out_lines = out_clean.split('\n') while '' in out_lines: out_lines.remove('') if module._diff: diff = {'prepared': out_clean} return module.exit_json(changed=changed, msg=out_clean, rc=rc, cmd=cmdstr, stdout_lines=out_lines, diff=diff) else: return module.exit_json(changed=changed, msg=out_clean, rc=rc, cmd=cmdstr, stdout_lines=out_lines)
def _get_shell_fragment(self): return "%s %s" % ( shlex_quote(self.program_fp.name), ' '.join(map(shlex_quote, self._get_program_args())), )
def cmd_to_str(cmd): return " ".join(shlex_quote(arg) for arg in cmd)