2012-03-23 94 views
3

我必须读取远程文件的内容,我有权限(sudo)使用 cat,less或tail读取。使用ruby Net :: 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” 远端已完成发送数据 壳终止

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

如何从channel.on_data中获取?

感谢

+0

我跑它放在我自己的日志文件之一,它工作得很好......没有等待,这是root用户,挂在实际用户 – DGM 2012-03-23 14:44:30

+0

-on预览,它在第一次发送密码之间挂了很长时间。 – user254694 2012-03-23 14:48:58

+0

您已验证该特定日志文件是否包含内容?如果你直接使用ssh,你会看到什么'ssh USER @ SERVER sudo cat/var/logs/httpd/ACCESS_log.2012.03.23' – dbenhur 2012-03-23 14:56:56

回答

1

我认为您需要为您发送的密码添加\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 
+0

我同意@dbenhur,多次调用on_data肯定会令人困惑,因为它取代了以前的代码块......保持所有处理在一个数据块中将是可取的。 – DGM 2012-03-23 15:08:59

+0

看起来像@DGM钉了它,密码需要一个“\ n”。与我的测试一起工作 – dbenhur 2012-03-23 17:20:30

0

在执行一个on_data回调要更换新on_data回调。我还没有深入研究Net :: SSH的内幕,但这可能会产生令人惊讶的行为。

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

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来读取日志,因此有人认为他们和该服务器值得保护。它看起来像你嵌入的密码,在这个红宝石程序中授予特权访问服务器。这意味着任何能够阅读该程序的人都可获得相同的特权访问权限。你会怎么做才能限制在这个程序中的密码?

+0

我现在在嵌入密码只是为了看看我能否得到一些工作。该解决方案的结果:在过程 过程 过程 数据处理 再没有什么作品 过程 过程 。这是其中的一件事情,其他代码示例让我这样做。这似乎是应该递归的东西.. – user254694 2012-03-23 14:58:25

-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