diff --git a/bin/ansible b/bin/ansible index c7abff01801..bff20f74cb9 100755 --- a/bin/ansible +++ b/bin/ansible @@ -91,9 +91,16 @@ if __name__ == '__main__': else: raise - cli = mycli(sys.argv) - cli.parse() - exit_code = cli.run() + try: + args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv] + except UnicodeError: + display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8') + display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc())) + exit_code = 6 + else: + cli = mycli(args) + cli.parse() + exit_code = cli.run() except AnsibleOptionsError as e: cli.parser.print_help() diff --git a/lib/ansible/utils/cmd_functions.py b/lib/ansible/utils/cmd_functions.py index 99f0483b599..b3a77e4c2c3 100644 --- a/lib/ansible/utils/cmd_functions.py +++ b/lib/ansible/utils/cmd_functions.py @@ -24,15 +24,26 @@ import shlex import subprocess import select +from ansible.compat.six import PY2 +from ansible.module_utils._text import to_bytes + def run_cmd(cmd, live=False, readsize=10): #readsize = 10 + # On python2, shlex needs byte strings + if PY2: + cmd = to_bytes(cmd, errors='surrogate_or_strict') cmdargs = shlex.split(cmd) + + # subprocess should be passed byte strings. (on python2.6 it must be + # passed byte strtings) + cmdargs = [to_bytes(a, errors='surrogate_or_strict') for a in cmdargs] + p = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout = '' - stderr = '' + stdout = b'' + stderr = b'' rpipes = [p.stdout, p.stderr] while True: rfd, wfd, efd = select.select(rpipes, [], rpipes, 1) @@ -42,14 +53,14 @@ def run_cmd(cmd, live=False, readsize=10): if live: sys.stdout.write(dat) stdout += dat - if dat == '': + if dat == b'': rpipes.remove(p.stdout) if p.stderr in rfd: dat = os.read(p.stderr.fileno(), readsize) stderr += dat if live: sys.stdout.write(dat) - if dat == '': + if dat == b'': rpipes.remove(p.stderr) # only break out if we've emptied the pipes, or there is nothing to # read from and the process has finished. diff --git a/lib/ansible/utils/display.py b/lib/ansible/utils/display.py index 8034f73ee3b..acf1aad3ec4 100644 --- a/lib/ansible/utils/display.py +++ b/lib/ansible/utils/display.py @@ -124,7 +124,7 @@ class Display: # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale - msg2 = to_text(msg2, self._output_encoding(stderr=stderr)) + msg2 = to_text(msg2, self._output_encoding(stderr=stderr), errors='replace') if not stderr: fileobj = sys.stdout diff --git a/test/integration/unicode.yml b/test/integration/unicode.yml index 74d5772264c..b22415a45d8 100644 --- a/test/integration/unicode.yml +++ b/test/integration/unicode.yml @@ -32,7 +32,7 @@ groups: 'ĪīĬĭ' ansible_ssh_host: 127.0.0.1 ansible_connection: local - with_items: hostnames + with_items: "{{ hostnames }}" - name: 'A task with unicode extra vars' debug: var=extra_var