Это не дубликат Как провести интерактивный сеанс SSH или Сценарий интерактивного терминала Net::SSH. Как? или Интерактивный ответ/ответ Ruby net-ssh
Я пытаюсь написать интерактивный SSH-клиент, используя Net:SSH, потому что я уже использую его для запуска неинтерактивных команд на целевых хостах.
Я мог бы просто раскошелиться на system "ssh"
, но это потребовало бы преобразования настроек подключения, проксирования и т. д. в параметры ssh
.
Проблема заключается в потоковой передаче данных из STDIN
в канал оболочки. Документация Net::SSH для listen_to
показывает, как это сделать, когда ввод осуществляется из сокета, а не из стандартного ввода. $stdin
или IO.console
не являются сокетами и поэтому несовместимы с Net::SSH::BufferedIo
.
Есть ли способ создать сокет из STDIN
, который можно использовать для этого? Или есть лучший способ отправить все от STDIN
до Net::SSH::Channel
, пока канал не закроется?
Вот код, который работает, но слишком медленный, чтобы его можно было использовать:
require 'net/ssh'
require 'io/console'
require 'io/wait'
Net::SSH.start('localhost', 'root') do |session|
session.open_channel do |channel|
channel.on_data do |_, data|
$stdout.write(data)
end
channel.on_extended_data do |_, data|
$stdout.write(data)
end
channel.request_pty do
channel.send_channel_request "shell"
end
channel.connection.loop do
$stdin.raw do |io|
input = io.readpartial(1024)
channel.send_data(input) unless input.empty?
end
channel.active?
end
end.wait
end