我必须阅读我有权阅读的(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中获取结果?
由于
答案 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