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

我必须读取一个远程文件的内容,我有权使用cat,less或tail读取(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中解决这个问题?

谢谢

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

需要'rubygems'
要求'net / ssh'

 cmd =“sudo cat /var/log/mail.log”
 HOSTNAME =“myhost.example.com”
 USERNAME =“我”
密码=“12345”


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

      channel.on_close做
       把“shell终止”
     结束
     channel.on_eof do | ch |
      把“远程端完成发送数据”
    结束
     channel.on_extended_data do | ch,type,data |
      把“得到stderr:#{data.inspect}”
    结束
     channel.on_data do | channel,data |
      如果#{USERNAME}的数据=〜/ ^ \ [sudo \]密码:/
        把“数据工作”
         channel.send_data“#{PASSWORD} \ n”
      其他
         #puts“OUTPUT NOT MATCHED:#{data}”
      结束
        channel.on_data do | ch,data |
         把“放在第三”
        把data.inspect
       结束
    结束
    channel.on_process do | ch |
     把“进行中”
   结束
   ssh.loop
  结束
结束

您正在执行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程序中提供对服务器的特权访问。 这意味着任何能够阅读该程序的人都可以获得相同的特权访问权限。 您将如何限制在此程序中访问密码?

 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 

最新文件17.11.25