5

我使用 Net::SSHv2 连接到服务器并在该服务器上启动脚本。到目前为止它正在工作,但我想在脚本运行超过 10 分钟或输出文件变得太大时中断脚本。收到中断后,脚本将关闭并输出一些统计信息。

我当前的代码如下所示:

File.open(filename, "w") do |f|
  Net::SSH.start(host, user, password: password) do |ssh|
    ssh.exec! "do_work"  do |channel, stream, data|
      f << "data"
      #break if f.size > 1024 * 1024 * 100 #file size > 100 MB
      #channel.send_data "^C" if f.size > 1024 * 1024 * 100 #file size > 100 MB
    end
  end
end

我尝试了其他一些方法,为通道打开一个块并请求一个 shell,但它没有用。

4

1 回答 1

1

send_data是正确的方法,但是:

  1. 您需要一个 PTY 才能将控制代码发送到服务器,这也意味着您需要在执行之前打开一个通道。
  2. 代码中没有任何内容可以理解插入符号 ( ^) 后跟大写 C 字符的人类显示约定,以表示“当您按下 CTRL+C 时发送由键盘 BIOS 生成的字符”。您必须发送 ASCII 字符本身,它是ETX(文本结尾)控制字符,在 C 十六进制转义序列中表示为\x03.
  3. 从技术上讲,这不是SIGINT信号——它是与 POSIX 信号 IPC 无关的终端中断信号,但 shell 通常将其解释ETX为“用户希望我向进程发送 SIGINT”——这是您需要的主要原因PTY - 它指示系统外壳遵守“键盘生成的控制字符应转换为信号”约定。目前无法通过常见的 SSH 实现通过 SSH 会话发送实际信号。有关更多详细信息,请参阅对类似(尽管不是 Ruby 特定)问题的答案。

您的代码应该如下所示:

File.open(filename, "w") do |f|
  Net::SSH.start(host, user, password: password) do |ssh|
    ssh.open_channel do |channel|
      channel.request_pty
      channel.exec "do_work" do |ch, success|
        raise "could not execute command: #{command.inspect}" unless success

        channel.on_data do |ch2, data|
          f << data
        end

        #break if f.size > 1024 * 1024 * 100 #file size > 100 MB
        channel.send_data "\x03" if f.size > 1024 * 1024 * 100 #file size > 100 MB
      end
    end.wait
  end
end

通道工作代码或多或少是从session.rb 源代码中逐字复制的。请参阅该内容以获取更多信息。

于 2018-12-13T15:18:51.203 回答