Hacker de código para impedir duplicidade de execução do cron do Moodle

Hacker de código para impedir duplicidade de execução do cron do Moodle

por Lino Vaz Moniz -
Número de respostas: 0

Para impedir que o cron processe em duplicidade, vamos implementar um hacker no código  que cancele a execução do próximo cron, caso exista um cron ainda em processamento.

Para implementar isso, siga os seguintes passos:


1) Abra o arquivo cronlib.php

Localize e abra o seguinte arquivo

MOODLE_INSTALL_DIR/lib/cronlib.php


2) Edite a função cron_run() 

Localize a função function cron_run()  essa função fica aproximadamente na linha 35 a 519

function cron_run() {
    global $DB, $CFG, $OUTPUT;
    .......
}

Adicione no inicio da função depois do código  global $DB, $CFG, $OUTPUT; o seguinte código:

//check exist cron running
$sql ="SELECT COUNT(id) AS countrecord FROM {$CFG->prefix}log WHERE  module =  'monitorcron'  AND action='cron_start' ";
$result=$DB->get_record_sql($sql);
if($result->countrecord > 0) {
	//add to log not process cron
	$crondto=new object();
	$crondto->time=time();
	$crondto->module='monitorcron';
	$crondto->action='cron_not_processed';
	$crondto->userid=2;
	$crondto->course=1;
	$crondto->ip=getremoteaddr();
	$crondto->url="cron_id_".time();
	$DB->insert_record('log', $crondto);
	echo "exist other cron running";
	return null;
}

//star log new cron
$crondto=new object();
$crondto->time=time();
$crondto->module='monitorcron';
$crondto->action='cron_start';
$crondto->userid=2;
$crondto->course=1;
$crondto->ip=getremoteaddr();
$crondto->url="cron_id_".time();
$DB->insert_record('log', $crondto);

//get id of new cron
$sql ="SELECT id FROM {$CFG->prefix}log WHERE  module =  'monitorcron'  AND action='cron_start' AND url='".$crondto->url."'   ";
$result=$DB->get_record_sql($sql);
$crondto->id=$result->id;
echo "cron id ". $crondto->id ." started ";


Esse código verifica se existe algum cron em execução. Se existir não processa. 


No final da função que fica aproximadamente na linha 519, antes de fechar a função adicione esse código:

// add to log end of cron
   $crondto->cmid=time();
   $crondto->action='cron_end';
   $crondto->info=$crondto->cmid-$crondto->time;

   if( $crondto->id>0){
	 $DB->update_record('log', $crondto);
    }
   echo "cron id ". $crondto->id. " end";


Esse trecho registra o encerramento do cron, usando a mesma chave do registro de log que iniciou o cron. 

Veja a função com com os códigos inseridos:

function cron_run() {
    global $DB, $CFG, $OUTPUT;
//código adicionado. registrar log de inicio 
//star log new cron
$crondto=new object();
$crondto->time=time();
$crondto->module='monitorcron';
$crondto->action='cron_start';
$crondto->userid=2;
$crondto->course=1;
$crondto->ip=getremoteaddr();
$crondto->url="cron_id_".time();
$DB->insert_record('log', $crondto);

//get id of new cron
$sql ="SELECT id FROM {$CFG->prefix}log WHERE  module =  'monitorcron'  AND action='cron_start' AND url='".$crondto->url."'   ";
$result=$DB->get_record_sql($sql);
$crondto->id=$result->id;
echo "cron id ". $crondto->id ." started ";

//código da lógica da função
 .......


//código adicionado. Registra log do fim da execução
// add to log end of cron
   $crondto->cmid=time();
   $crondto->action='cron_end';
   $crondto->info=$crondto->cmid-$crondto->time;

   if( $crondto->id>0){
	 $DB->update_record('log', $crondto);
    }
   echo "cron id ". $crondto->id. " end";
}

Salve as alterações feitas no arquivo


3) Consultor log com SQL

Para rastrear o log do cron, execute o seguinte comando SQL:

Verifique se existe cron em processamento

SELECT COUNT(id) AS countrecord FROM mdl_log WHERE  module =  'monitorcron'  AND action='cron_start'


Encerre manualmente o processamento do cron

UPDATE mdl_log SET action='cron_end_manual'  WHERE  module =  'monitorcron'  AND action='cron_start';


Consultar log de cron 

SELECT id,url AS idcontnrol,action,time AS timestart, cmid AS timeend, info AS duration FROM mdl_log WHERE  module =  'monitorcron';