Commit 7192eb30 by Dag Wieers

Use proper pseudo-tty's instead of pipes when using subprocess

This change avoids the "tcgetattr: Invalid argument" error by making sure the ssh we start does have a proper pseudo-tty.

We could also check whether our current terminal is a proper terminal (by doing a tcgetattr ourselves) but I don't think this adds anything.

This closes #1662 (if all use-cases have been tested: sudo, passwd)
parent d1c285b7
...@@ -99,8 +99,17 @@ class Connection(object): ...@@ -99,8 +99,17 @@ class Connection(object):
ssh_cmd.append(cmd) ssh_cmd.append(cmd)
vvv("EXEC %s" % ssh_cmd, host=self.host) vvv("EXEC %s" % ssh_cmd, host=self.host)
try:
# Make sure stdin is a proper (pseudo) pty to avoid: tcgetattr errors
import pty
master, slave = pty.openpty()
p = subprocess.Popen(ssh_cmd, stdin=slave,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdin = os.fdopen(master, 'w', 0)
except:
p = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE, p = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdin = p.stdin
self._send_password() self._send_password()
...@@ -118,7 +127,7 @@ class Connection(object): ...@@ -118,7 +127,7 @@ class Connection(object):
else: else:
stdout = p.communicate() stdout = p.communicate()
raise errors.AnsibleError('ssh connection error waiting for sudo password prompt') raise errors.AnsibleError('ssh connection error waiting for sudo password prompt')
p.stdin.write(self.runner.sudo_pass + '\n') stdin.write(self.runner.sudo_pass + '\n')
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK) fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
# We can't use p.communicate here because the ControlMaster may have stdout open as well # We can't use p.communicate here because the ControlMaster may have stdout open as well
...@@ -133,7 +142,7 @@ class Connection(object): ...@@ -133,7 +142,7 @@ class Connection(object):
break break
elif p.poll() is not None: elif p.poll() is not None:
break break
p.stdin.close() # close stdin after we read from stdout (see also issue #848) stdin.close() # close stdin after we read from stdout (see also issue #848)
if p.returncode != 0 and stdout.find('Bad configuration option: ControlPersist') != -1: if p.returncode != 0 and stdout.find('Bad configuration option: ControlPersist') != -1:
raise errors.AnsibleError('using -c ssh on certain older ssh versions may not support ControlPersist, set ANSIBLE_SSH_ARGS="" (or ansible_ssh_args in the config file) before running again') raise errors.AnsibleError('using -c ssh on certain older ssh versions may not support ControlPersist, set ANSIBLE_SSH_ARGS="" (or ansible_ssh_args in the config file) before running again')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment