6

有什么方法可以使用 net-ssh 在 ruby​​ 中获取登录 shell?这甚至可能吗?

通过登录外壳,我的意思是源 /etc/profile..

4

2 回答 2

14

Net-SSH 的级别太低,无法简单地预先提供(无论如何都是现在的方式)。您可以查看基于 Net-SSH 构建的 Net-SSH-Shell 以添加登录 shell 功能:https ://github.com/mitchellh/net-ssh-shell

该实现是可靠的并且可以工作,但是我发现它不太有用,因为您无法专门提取诸如 stderr 或退出状态之类的内容,因为命令在子 shell 中运行,因此您只能获取 stdout。net-ssh-shell 库使用一些技巧来获取退出状态。

我自己的 Ruby 项目需要一个“登录 shell”,为此我通常使用以下代码直接在 shell 中执行操作:

def execute_in_shell!(commands, shell="bash")
  channel = session.open_channel do |ch|
    ch.exec("#{shell} -l") do |ch2, success|
      # Set the terminal type
      ch2.send_data "export TERM=vt100\n"

      # Output each command as if they were entered on the command line
      [commands].flatten.each do |command|
        ch2.send_data "#{command}\n"
      end

      # Remember to exit or we'll hang!
      ch2.send_data "exit\n"

      # Configure to listen to ch2 data so you can grab stdout
    end
  end

  # Wait for everything to complete
  channel.wait
end

使用此解决方案,您仍然不会获得退出状态或命令的 stderr 运行到登录 shell,但至少命令是在该上下文中执行的。

我希望这有帮助。

于 2011-03-17T19:43:34.903 回答
0

现在有一种更好的方法可以做到这一点。相反,您可以使用带有 pty 的 shell 子系统来获取您期望从 shell 登录中获得的所有内容:

Net::SSH.start(@config.host, @config.user, :port => @config.port, :keys => @config.key, :config => true) do |session|
  session.open_channel do |channel|
    channel.request_pty
    channel.send_channel_request "shell" do |ch, success|
      if success
        ch.send_data "env\n"
        ch.send_data "#{command}\n"
        ch.on_data do |c, data|
          puts data
        end
      end
      channel.send_data "exit\n"

      channel.on_close do
        puts "shell closed"
      end
    end
  end
end

结尾

于 2018-05-06T14:20:18.080 回答