Merge pull request #4408 from lsimons/ssh-scrub-pty-output-for-upstream

core: Scrub SSH PTY output to filter out command echo-ing and most other cruft
This commit is contained in:
Mitchell Hashimoto 2014-08-29 09:33:10 -07:00
commit a9be7ce224
1 changed files with 45 additions and 5 deletions

View File

@ -401,6 +401,9 @@ module VagrantPlugins
return yield connection if block_given?
end
DELIM_START = 'UniqueStartStringPTY'
DELIM_END = 'UniqueEndStringPTY'
# Executes the command on an SSH connection within a login shell.
def shell_execute(connection, command, **opts)
opts = {
@ -421,10 +424,14 @@ module VagrantPlugins
shell_cmd = shell if shell
shell_cmd = "sudo -E -H #{shell_cmd}" if sudo
use_tty = false
stdout = ''
# Open the channel so we can execute or command
channel = connection.open_channel do |ch|
if @machine.config.ssh.pty
ch.request_pty do |ch2, success|
use_tty = success and command != ''
if success
@logger.debug("pty obtained for connection")
else
@ -439,7 +446,11 @@ module VagrantPlugins
# Filter out the clear screen command
data = remove_ansi_escape_codes(data)
@logger.debug("stdout: #{data}")
yield :stdout, data if block_given?
if use_tty
stdout << data
else
yield :stdout, data if block_given?
end
end
ch2.on_extended_data do |ch3, type, data|
@ -487,14 +498,31 @@ module VagrantPlugins
end
# Output the command
ch2.send_data "#{command}\n".force_encoding('ASCII-8BIT')
# Remember to exit or this channel will hang open
ch2.send_data "exit\n"
if use_tty
ch2.send_data "stty raw -echo\n"
ch2.send_data "export PS1=\n"
ch2.send_data "export PS2=\n"
ch2.send_data "export PROMPT_COMMAND=\n"
sleep(0.1)
data = "printf #{DELIM_START}\n"
data += "#{command}\n"
data += "exitcode=$?\n"
data += "printf #{DELIM_END}\n"
data = data.force_encoding('ASCII-8BIT')
ch2.send_data data
# Remember to exit or this channel will hang open
ch2.send_data "exit $exitcode\n"
else
ch2.send_data "#{command}\n".force_encoding('ASCII-8BIT')
# Remember to exit or this channel will hang open
ch2.send_data "exit\n"
end
# Send eof to let server know we're done
ch2.eof!
ch2.wait
end
ch.wait
end
begin
@ -520,6 +548,7 @@ module VagrantPlugins
@logger.info(
"SSH connection unexpected closed. Assuming reboot or something.")
exit_status = 0
use_tty = false
rescue Net::SSH::ChannelOpenFailed
raise Vagrant::Errors::SSHChannelOpenFail
rescue Net::SSH::Disconnect
@ -530,6 +559,17 @@ module VagrantPlugins
keep_alive.kill if keep_alive
end
if use_tty
@logger.debug("stdout: #{stdout}")
if not stdout.include? DELIM_START or not stdout.include? DELIM_END
@logger.error("Error parsing TTY output")
raise Vagrant::Errors::SSHInvalidShell.new
end
data = stdout[/.*#{DELIM_START}(.*?)#{DELIM_END}/m, 1]
@logger.debug("selected stdout: #{data}")
yield :stdout, data if block_given?
end
# Return the final exit status
return exit_status
end