@ -241,7 +241,7 @@ class Connection(ConnectionBase):
return self . _command
def _send_initial_data ( self , fh , in_data , tty = False ):
def _send_initial_data ( self , fh , in_data ):
'''
Writes initial data to the stdin filehandle of the subprocess and closes
it . ( The handle must be closed ; otherwise , for example , " sftp -b - " will
@ -252,8 +252,6 @@ class Connection(ConnectionBase):
try :
fh . write ( in_data )
if tty :
fh . write ( " __EOF__942d747a0772c3284ffb5920e234bd57__ \n " )
fh . close ( )
except ( OSError , IOError ) :
raise AnsibleConnectionFailure ( ' SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh ' )
@ -316,7 +314,7 @@ class Connection(ConnectionBase):
return ' ' . join ( output ) , remainder
def _run ( self , cmd , in_data , sudoable = True , tty = False ):
def _run ( self , cmd , in_data , sudoable = True ):
'''
Starts the command and communicates with it until it ends .
'''
@ -324,10 +322,25 @@ class Connection(ConnectionBase):
display_cmd = map ( pipes . quote , cmd [ : - 1 ] ) + [ cmd [ - 1 ] ]
display . vvv ( ' SSH: EXEC {0} ' . format ( ' ' . join ( display_cmd ) ) , host = self . host )
# Start the given command.
# Start the given command. If we don't need to pipeline data, we can try
# to use a pseudo-tty (ssh will have been invoked with -tt). If we are
# pipelining data, or can't create a pty, we fall back to using plain
# old pipes.
p = subprocess . Popen ( cmd , stdin = subprocess . PIPE , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
stdin = p . stdin
p = None
if not in_data :
try :
# Make sure stdin is a proper pty to avoid tcgetattr errors
master , slave = pty . openpty ( )
p = subprocess . Popen ( cmd , stdin = slave , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
stdin = os . fdopen ( master , ' w ' , 0 )
os . close ( slave )
except ( OSError , IOError ) :
p = None
if not p :
p = subprocess . Popen ( cmd , stdin = subprocess . PIPE , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
stdin = p . stdin
# If we are using SSH password authentication, write the password into
# the pipe we opened in _build_command.
@ -390,7 +403,7 @@ class Connection(ConnectionBase):
# before we call select.
if states [ state ] == ' ready_to_send ' and in_data :
self . _send_initial_data ( stdin , in_data , tty )
self . _send_initial_data ( stdin , in_data )
state + = 1
while True :
@ -488,7 +501,7 @@ class Connection(ConnectionBase):
if states [ state ] == ' ready_to_send ' :
if in_data :
self . _send_initial_data ( stdin , in_data , tty )
self . _send_initial_data ( stdin , in_data )
state + = 1
# Now we're awaiting_exit: has the child process exited? If it has,
@ -544,9 +557,17 @@ class Connection(ConnectionBase):
display . vvv ( " ESTABLISH SSH CONNECTION FOR USER: {0} " . format ( self . _play_context . remote_user ) , host = self . _play_context . remote_addr )
cmd = self . _build_command ( ' ssh ' , ' -tt ' , self . host , cmd )
# we can only use tty when we are not pipelining the modules. piping
# data into /usr/bin/python inside a tty automatically invokes the
# python interactive-mode but the modules are not compatible with the
# interactive-mode ("unexpected indent" mainly because of empty lines)
if in_data :
cmd = self . _build_command ( ' ssh ' , self . host , cmd )
else :
cmd = self . _build_command ( ' ssh ' , ' -tt ' , self . host , cmd )
( returncode , stdout , stderr ) = self . _run ( cmd , in_data , sudoable = sudoable , tty = True )
( returncode , stdout , stderr ) = self . _run ( cmd , in_data , sudoable = sudoable )
return ( returncode , stdout , stderr )