首页 > 解决方案 > 使用 Net::SSH 或创建 STDIN 套接字的交互式 SSH 会话

问题描述

这不是如何 SSH 交互式会话Net::SSH 交互式终端脚本的副本。如何?Ruby net-ssh 交互式响应/回复

我正在尝试使用 Net:SSH 编写交互式 SSH 客户端,因为我已经在使用它在目标主机上运行非交互式命令。

我可以直接使用,system "ssh"但这需要将连接设置、代理等转换为ssh参数。

问题是将数据流式传输STDIN到 shell 通道。Net::SSH 文档listen_to展示了当输入来自套接字而不是 STDIN 时如何执行此操作。$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

标签: rubynet-ssh

解决方案


套接字实际上只不过是文件描述符,并且由于 STDIN 也是文件描述符,因此尝试一下也无妨。

但是,您想要的是首先将 TTY 置于原始模式以获得交互性。
这段代码似乎工作正常:

begin
  system('stty cbreak -echo')

  Net::SSH.start(...) do |session|
    session.open_channel do |...|
       ...
       session.listen_to(STDIN) { |stdin|
         input = stdin.readpartial(1024)
         channel.send_data(input) unless input.empty?
       }
     end.wait
   end
ensure
  system('stty sane')
end

推荐阅读