如何将SIGINT发送到Net :: SSH会话中的进程startet?

时间:2013-07-16 15:19:16

标签: ruby net-ssh

我使用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,但它没有用。

1 个答案:

答案 0 :(得分:0)

send_data是正确的方法,但是:

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

您的代码应该看起来像这样:

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 source code逐字复制了频道工作代码。有关更多信息,请参考。