【问题标题】:Interactive SSH session using Net::SSH or creating a STDIN Socket使用 Net::SSH 或创建 STDIN 套接字的交互式 SSH 会话
【发布时间】:2018-10-26 19:25:04
【问题描述】:

这不是 How to SSH interactive SessionNet::SSH interactive terminal scripting. How?Ruby net-ssh interactive response/reply 的副本

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

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

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

【问题讨论】:

    标签: ruby net-ssh


    【解决方案1】:

    套接字实际上只不过是文件描述符,而且由于 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
    

    【讨论】:

    • 应该尝试不使用Net::SSH::BufferedIo,这会导致NoMethodError 用于STDIN.recv。看起来这样行得通。 stty 的东西,我相信可以用$stdin.raw!; $stdin.echo = false; 代替。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 2016-03-28
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多