使用ruby Net :: SSH通过sudo读取远程文件

时间:2012-03-23 14:05:13

标签: ruby ssh

我必须阅读我有权阅读的(sudo)远程文件的内容 猫,少或尾。

我将在Ruby中执行此操作,因此我假设我应该使用Net :: SSH来执行此操作。

该文件是一个日志文件,所以它可能非常大。

这是我现在正在尝试的代码:

require 'rubygems'
require 'net/ssh'

cmd = "sudo cat /var/logs/httpd/ACCESS_log.2012.03.23"

Net::SSH.start( "SERVER" , "USER", :password => "PASSWORD") do |ssh|
  ssh.open_channel do |channel|
    channel.request_pty
     channel.exec(cmd);

     channel.on_close do
       puts "shell terminated"
     end
    channel.on_eof do |ch|
      puts "remote end is done sending data"
    end
    channel.on_extended_data do |ch, type, data|
      puts "got stderr: #{data.inspect}"
    end
    channel.on_data do |channel, data|
      if data =~ /^\[sudo\] password for USER:/
        puts "data works"
        channel.send_data 'PASSWORD'
      end
     channel.on_data do |ch,data|
        puts "in third"
        puts data.inspect
     end
    end
   channel.on_process do |ch|
     puts "in process"
   end
  ssh.loop
  end
end

当我运行时,我得到以下输出:

正在进行中 正在进行中 正在进行中 数据有效 正在进行中 正在进行中 正在进行中 在第三 “\ r \ n” 远程端完成发送数据 shell终止

日志实际上当前有几千行数据,因为我可以使用putty从实际服务器读取它。

如何从channel.on_data中获取结果?

由于

3 个答案:

答案 0 :(得分:2)

我认为您需要在发送的密码中添加\n。这适合我。注意,在我注释掉else子句的地方,你也可以从那里获取信息,但它可以正常工作,但密码中有\n

require 'rubygems'
require 'net/ssh'

cmd = "sudo cat /var/log/mail.log"
HOSTNAME = "myhost.example.com"
USERNAME = "me"
PASSWORD = "12345"


Net::SSH.start( HOSTNAME , USERNAME, :password => PASSWORD) do |ssh|
  ssh.open_channel do |channel|
    channel.request_pty
     channel.exec(cmd);

     channel.on_close do
       puts "shell terminated"
     end
    channel.on_eof do |ch|
      puts "remote end is done sending data"
    end
    channel.on_extended_data do |ch, type, data|
      puts "got stderr: #{data.inspect}"
    end
    channel.on_data do |channel, data|
      if data =~ /^\[sudo\] password for #{USERNAME}:/
        puts "data works"
        channel.send_data "#{PASSWORD}\n"
      else
        #puts "OUTPUT NOT MATCHED: #{data}"
      end
       channel.on_data do |ch,data|
         puts "in third"
        puts data.inspect
       end
    end
   channel.on_process do |ch|
     puts "in process"
   end
  ssh.loop
  end
end

答案 1 :(得分:0)

您正在执行on_data回调时替换新的on_data回调。我没有考虑Net :: SSH的内部,但这可能会产生令人惊讶的行为。

尝试将两个on_data回调中的代码更改为一个,看看是否有帮助。

channel.on_data do |channel, data|
  if data =~ /^\[sudo\] password for USER:/
    puts "data works"
    channel.send_data 'PASSWORD'
  else
    puts "in third"
    puts data.inspect
  if
end

作为旁注,由于您需要sudo来阅读日志,因此有人认为他们和该服务器值得保护。看起来你正在嵌入密码,这些密码可以在这个ruby程序中提供对服务器的特权访问。这意味着任何能够阅读该程序的人都可以获得相同的特权访问权限。您将如何限制在此程序中访问密码?

答案 2 :(得分:-1)

require 'net/ssh'

Net::SSH.start('host', 'user', :password => "password") do |ssh|
  # capture all stderr and stdout output from a remote process
  output = ssh.exec!("hostname")
  puts output

  # capture only stdout matching a particular pattern
  stdout = ""
  ssh.exec!("ls -l /home/jamis") do |channel, stream, data|
    stdout << data if stream == :stdout
  end
  puts stdout

  # run multiple processes in parallel to completion
  ssh.exec "sed ..."
  ssh.exec "awk ..."
  ssh.exec "rm -rf ..."
  ssh.loop

  # open a new channel and configure a minimal set of callbacks, then run
  # the event loop until the channel finishes (closes)
  channel = ssh.open_channel do |ch|
    ch.exec "/usr/local/bin/ruby /path/to/file.rb" do |ch, success|
      raise "could not execute command" unless success

      # "on_data" is called when the process writes something to stdout
      ch.on_data do |c, data|
        $stdout.print data
      end

      # "on_extended_data" is called when the process writes something to stderr
      ch.on_extended_data do |c, type, data|
        $stderr.print data
      end

      ch.on_close { puts "done!" }
    end
  end

  channel.wait

  # forward connections on local port 1234 to port 80 of www.capify.org
  ssh.forward.local(1234, "www.capify.org", 80)
  ssh.loop { true }
end

Latest Document 17.11.25