=begin
Coletor do Sisope.
Organiza as threads e envia os dados.
Feito por Ruivaldo Neto
=end
$: << "/home/sisope/"
$DEBUG = true
##
# Aqui você pode ver que usamos poucas dependências :)
require 'logger'
require 'date'
require 'time'
require 'net/http'
require 'infocentro.rb'
require 'yaml'
##
# Configurando o logger
$log = Logger.new(STDOUT)
$log.level = Logger::DEBUG
$log.datetime_format = "%H:%M:%S"
$log.info("Iniciando coletor")
##
# Constantes
$EnderecoServidor = ""
$ArquivoReenvio = ""
##
# Método para esperar X minutos
def sleep_minutos(minutos)
sleep minutos # * 60
end
##
# Classe coletora
class Coletor
def initialize
@infocentro = Infocentro.new
@coletas = []
end
##
# Verifica se o id do infocentro está configurado.
def verificar_id_configurado
if @infocentro.coletar_id.nil?
exit 1
end
end
##
# Verifica se os arquivos necessários as coletas existem, senão, cria.
def verificar_arquivos_necessarios
if not File.exists?('/var/log/lastlog')
system('cat /dev/null > /var/log/lastlog')
end
if not File.exists?('/var/log/wtmp')
system('cat /dev/null > /var/log/wtmp')
end
end
##
# Envia os dados através de uma requisição POST simulada.
def enviar_para(endereco, parametros, tentativa=0)
# Verifica se o numero de tentativas excedeu o limite de dez.
if tentativa == 10
#$log.warn("Salvando para reenvio: #{endereco} - #{parametros.inspect}")
salvar_para_reenvio(endereco, parametros)
return false
end
#$log.info("Tentando enviar: #{endereco} - #{parametros.inspect}")
resposta = Net::HTTP.post_form(URI.parse(endereco), parametros)
if resposta.code.to_i == 200
#$log.info("Enviado: #{endereco} - #{parametros.inspect}")
return true
end
rescue SocketError => e
#$log.warn("Falha na transmissão: #{endereco} - #{parametros.inspect}")
sleep 6 # Dorme 6 segundos para não sobrecarregar o servidor.
self.enviar_para(endereco, parametros, tentativa+1)
rescue SystemStackError => e
#$log.debug("Muitas tentativas de envio feitas. Abortando.")
end
##
# Salva o endereco e os parametros numa lista para reenvio
def salvar_para_reenvio(endereco, parametros)
grupo = endereco.split("/")[-1]
endereco = $EnderecoServidor + 'reenvio_' + grupo
parametros["data"] = Date.today.strftime("%d/%m/%Y")
parametros["horario"] = Time.now.strftime("%H:%m:%S")
lista_de_envio = carregar_lista_reenvio()
lista_de_envio << {:endereco => endereco, :parametros => parametros}
alterar_lista_reenvio(lista_de_envio)
end
##
# Carregar lista reenvio
def carregar_lista_reenvio
lista_de_envio = YAML.load(File.open($ArquivoReenvio, "r+"))
if lista_de_envio.nil?
lista_de_envio = []
end
return lista_de_envio
end
##
# Escreve na lista de reenvio uma nova lista
def alterar_lista_reenvio(nova_lista)
File.open($ArquivoReenvio, "w") { |fp| YAML.dump(nova_lista, fp) }
end
##
# Pegar proximo elemento no reenvio
def proximo_reenvio()
lista_envio = carregar_lista_reenvio()
item_reenvio = lista_envio[0]
return item_reenvio
end
##
# Executar reenvio
# Pega o primeiro item da lista de reenvio a cada uma hora
# E tenta enviar. Se conseguir, remove-o da lista.
def executar_reenvio()
while true
item_reenvio = proximo_reenvio()
#$log.debug(item_reenvio.inspect)
unless item_reenvio.nil? || item_reenvio.empty?
#$log.info("Reenviando: #{item_reenvio[:endereco]} #{item_reenvio[:parametros].inspect}")
resposta = self.reenvio(item_reenvio[:endereco], item_reenvio[:parametros])
if resposta == 200
## This line is bogus, look: item_reeEnvio
$log.info("Reenviado com exito: #{item_reeenvio[:endereco]} - #{item_reenvio[:parametros].inspect}")
##
prosseguir_lista_reenvio()
$log.debug(carregar_lista_reenvio())
else
#$log.info("Falha ao reenviar: #{item_reenvio[:endereco]} - #{item_reenvio[:parametros].inspect.inspect}")
end
else
#$log.info("Nao ha items setados para reenvio")
end
sleep_minutos(10) # Dorme por uma hora
end
end
##
# Prosseguir lista de reenvio
# Remove o primeiro e pula para o proximo
def prosseguir_lista_reenvio()
lista_envio = carregar_lista_reenvio()
lista_envio.shift unless lista_envio.nil? || lista_envio.empty?
alterar_lista_reenvio(lista_envio)
end
##
# Método enviar_para_reenvio
# É um enviar para sem repetição
def reenvio(endereco, parametros)
begin
resposta = Net::HTTP.post_form(URI.parse(endereco), parametros)
return resposta.code.to_i
rescue SocketError => e
return 404
end
end
##
# Envia o primeiro grupo de coleta.
def executar_coleta_grupo1
parametros = {}
while true
parametros['id'] = @infocentro.coletar_id
parametros['qad'] = @infocentro.coletar_qad
parametros['qul'] = @infocentro.coletar_qul
parametros['qtl'] = @infocentro.coletar_qtl
parametros['hd'] = @infocentro.coletar_hd
self.enviar_para($EnderecoServidor + "grupo1.php", parametros)
sleep_minutos(10) # Aguarda por dez minutos.
end
end
##
# Executar coleta grupo 2.
def executar_coleta_grupo2
parametros = {}
while true
parametros['id'] = @infocentro.coletar_id
parametros['ocupacao_home'] = @infocentro.coletar_ocupacao_home
parametros['ocupacao_raiz'] = @infocentro.coletar_ocupacao_raiz
parametros['quantidade_impressao'] = @infocentro.coletar_quantidade_impressao
parametros['quantidade_login_root'] = @infocentro.coletar_quantidade_login_root
parametros['versao_berimbau'] = @infocentro.coletar_versao_berimbau
parametros['quantidade_usuario_cadastrado'] = @infocentro.coletar_quantidade_usuario_cadastrado
self.enviar_para($EnderecoServidor + "grupo2.php", parametros)
sleep_minutos(120) # Envia a cada duas horas
end
end
###
# Coleta pld.
def coletar_pld()
sleep_minutos(60) # Espera uma hora até o primeiro login.
parametros = {}
parametros['id'] = @infocentro.coletar_id
parametros['pld'] = @infocentro.coletar_primeiro_login
self.enviar_para($EnderecoServidor + 'pld1.php', parametros)
end
###
# Iniciar coletas.
def iniciar_coleta()
# Coleta do pld
@coletas << Thread.new { self.coletar_pld }
# Adiciona coleta do grupo 1 ;)
@coletas << Thread.new { self.executar_coleta_grupo1 }
# Adiciona a coleta do grupo 2
@coletas << Thread.new { self.executar_coleta_grupo2 }
# Adiciona o reenvio
@coletas << Thread.new { self.executar_reenvio }
# Inicia as threads. O método join faz o programa executar até elas terminarem.
@coletas.each {|c| c.abort_on_exception = true}
@coletas.each {|c| c.join}
end
end
###
# Inicia a execução do script.
coletor = Coletor.new
coletor.verificar_id_configurado
coletor.verificar_arquivos_necessarios
coletor.iniciar_coleta