используйте ruby ​​Net :: SSH для чтения удаленного файла через sudo - PullRequest
3 голосов
/ 23 марта 2012

Мне нужно прочитать содержимое удаленного файла, для которого у меня есть права на чтение (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

Когда я запускаю это, я получаю следующий вывод:

в процессе в процессе в процессе данные работают в процессе в процессе в процессе в третьем «\ Г \ п» удаленный конец сделал отправку данных оболочка прекращена

На самом деле в журнале в настоящее время содержится несколько тысяч строк данных, потому что я могу читать его с реального сервера, используя замазку.

Как мне получить это из channel.on_data?

Спасибо

Ответы [ 3 ]

2 голосов
/ 23 марта 2012

Я думаю, вам нужно добавить \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 голосов
/ 25 ноября 2017
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

0 голосов
/ 23 марта 2012

Вы заменяете новый 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. Это означает, что любой, кто может читать программу, получает такой же привилегированный доступ. Что вы будете делать, чтобы ограничить доступ к паролю в этой программе?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...