Use ruby ​​Net :: SSH to read remote file via sudo

I need to read the contents of a remote file to which I have permissions (sudo) using cat, less or tail.

I'm going to do this in Ruby, so I guess I should be using Net :: SSH to do this.

The file is a log file, so it can be quite large.

This is the code I'm trying now:

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

      

When I run I get the following output:

in process in process in process data work in process in process in process in third "\ r \ n" remote end completes sending data shell finished

Currently there are several thousand lines of data in the log because I can read it from a real server with putty.

How do I get this from channel.on_data?

thank

+3


source to share


3 answers


I think you need to add \n

to the password you are sending. This works for me. Note. At the place where I commented out the else clause, you can also get information from there, but it works the way you are, but with \n

in the password.



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


source


You are replacing the new callback on_data

when you execute the callback on_data

. I didn't do the internal processing of Net :: SSH, but it could cause surprising behavior.

Try changing the code in your two on_data callbacks to be the same and see if that helps.



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

      

As a side note, since you need sudo to read the logs, someone thinks they and this server deserve protection. It looks like you are embedding passwords that grant privileged access to the server in this ruby ​​program. This means that anyone who can read the program gets the same privileged access. What will you do to restrict password access in this program?

0


source


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

      

Last document 11/17/25

-1


source







All Articles