¿Cómo ejecutar una función cada 5 minutos?

10 nov 2015, 10:47:43
Vistas: 81.1K
Votos: 25

Tengo una función que necesito ejecutar cada 5 minutos. He consultado lo siguiente en el codex:

<?php wp_schedule_event(time(), 'hourly', 'my_schedule_hook', $args); ?> 

Quiero ejecutar esta función cada 5 minutos independientemente de cuándo comience. ¿Cómo puedo hacer esto?

Además, el codex menciona que el cron se ejecutará cuando un visitante acceda al sitio. ¿Hay alguna manera de ejecutar el cron según los minutos establecidos sin esperar una visita?

Por ejemplo, si la siguiente función debe ejecutarse cada 5 minutos, ¿cómo puedo hacerlo usando wp_schedule_event() o wp_cron?

function run_evry_five_minutes(){
    // el código va aquí
}
5
Comentarios

Sería mejor que consideres, por ejemplo, Linux cron o servicios de cron de terceros si necesitas un intervalo tan corto y precisión,

birgire birgire
10 nov 2015 10:58:45

el sitio tiene mucho tráfico... así que no hay necesidad de considerar el intervalo de tiempo... seguro que se activará cada 2 o 3 minutos... los clientes prefieren hacerlo desde functions.php

foolishcoder7721 foolishcoder7721
10 nov 2015 11:01:48

no es posible activar un archivo php sin que algo se ejecute en el servidor con un temporizador.

Andrew Welch Andrew Welch
10 nov 2015 11:16:50

¿archivo? estamos hablando de una función en functions.php

foolishcoder7721 foolishcoder7721
10 nov 2015 11:18:27

¿Crees que un servicio de monitoreo gratuito podría ser el ping que active CRON? http://newrelic.com/server-monitoring

jgraup jgraup
30 ene 2016 20:49:15
Todas las respuestas a la pregunta 7
0
52

Puedes crear nuevos intervalos de programación mediante cron_schedules:

function my_cron_schedules($schedules){
    if(!isset($schedules["5min"])){
        $schedules["5min"] = array(
            'interval' => 5*60,
            'display' => __('Una vez cada 5 minutos'));
    }
    if(!isset($schedules["30min"])){
        $schedules["30min"] = array(
            'interval' => 30*60,
            'display' => __('Una vez cada 30 minutos'));
    }
    return $schedules;
}
add_filter('cron_schedules','my_cron_schedules');

Ahora puedes programar tu función:

wp_schedule_event(time(), '5min', 'my_schedule_hook', $args);

Para programarla solo una vez, envuélvela en una función y verifica antes de ejecutarla:

$args = array(false);
function schedule_my_cron(){
    wp_schedule_event(time(), '5min', 'my_schedule_hook', $args);
}
if(!wp_next_scheduled('my_schedule_hook',$args)){
    add_action('init', 'schedule_my_cron');
}

¡Nota el parámetro $args! No especificar el parámetro $args en wp_next_scheduled, pero tener $args para wp_schedule_event, causará que se programen casi infinitamente el mismo evento (en lugar de solo uno).

Finalmente, crea la función real que deseas ejecutar:

function my_schedule_hook(){
    // tu código aquí
}

Creo que es importante mencionar que wp-cron verifica el programa y ejecuta los trabajos pendientes cada vez que se carga una página.

Por lo tanto, si tienes un sitio web con poco tráfico que solo recibe 1 visitante por hora, wp-cron solo se ejecutará cuando ese visitante navegue por tu sitio (una vez por hora). Si tienes un sitio con mucho tráfico donde los visitantes solicitan una página cada segundo, wp-cron se activará cada segundo causando carga adicional en el servidor.

La solución es desactivar wp-cron y activarlo mediante un trabajo cron real en el intervalo de tiempo de tu tarea programada más frecuente (5 minutos en tu caso).

Lucas Rolff explica el problema y da la solución en detalle.

Como alternativa, podrías usar un servicio gratuito de terceros como UptimeRobot para consultar tu sitio (y activar wp-cron) cada 5 minutos, si no deseas desactivar wp-cron y activarlo mediante un cron real.

30 ene 2016 01:23:34
7

Si tu sitio recibe mucho tráfico, podrías intentar usar set_transient() para ejecutarlo (de forma muy aproximada) cada 5 minutos, por ejemplo:

function run_every_five_minutes() {
    // Probablemente necesitaría algo de lógica aquí para evitar que se ejecute justo después de haberlo hecho.
    // el código va aquí
}

if ( ! get_transient( 'every_5_minutes' ) ) {
    set_transient( 'every_5_minutes', true, 5 * MINUTE_IN_SECONDS );
    run_every_five_minutes();

    // Es mejor usar un hook para llamar a una función en el plugin/tema
    //add_action( 'init', 'run_every_five_minutes' );
}
10 nov 2015 12:24:05
Comentarios

Bueno, eh, ¡¿sí?!...

bonger bonger
10 nov 2015 13:10:06

sí.. NO está funcionando.. he usado el siguiente código en functions.php cuando se visita la página, se debe hacer una actualización en una tabla de mi base de datos.. function run_evry_five_minutes() { $homepage = file_get_contents('link to visit'); echo $homepage; }. Pero la tabla de la base de datos no se actualiza después de 6 minutos.

foolishcoder7721 foolishcoder7721
10 nov 2015 13:43:49

No sé por qué no te funciona, pero pensándolo bien, usar simplemente get_transient()/set_transient() sin lo del cron tiene mucho más sentido, es mucho más simple, actualizaré la respuesta...

bonger bonger
10 nov 2015 14:03:40

@bonger ¿es esta una buena alternativa para wp_schedule_event()?

Marko Kunic Marko Kunic
8 may 2016 22:16:10

@MarkoKunić No lo sé sinceramente, no lo he probado... solo se ofreció como solución alternativa pero si lo pruebas háznoslo saber...! (La respuesta de Johano Fierra parece buena http://wordpress.stackexchange.com/a/216121/57034 )

bonger bonger
9 may 2016 14:55:31

@bonger está funcionando, pero es lo mismo, si no estás en el sitio web, no se ejecutará

Marko Kunic Marko Kunic
10 may 2016 10:00:14

Sí, como se mencionó en varios lugares de esta página, necesitas un trabajo cron real de alguna forma u otra para hacerlo sin requerir visitantes... (gracias por el feedback, de todas formas.)

bonger bonger
11 may 2016 09:20:25
Mostrar los 2 comentarios restantes
0

La respuesta de @johano explica correctamente cómo configurar un intervalo personalizado para un trabajo cron en WordPress. Sin embargo, la segunda pregunta no está respondida, que es cómo ejecutar un cron cada minuto:

  1. En el archivo wp-config.php, agrega el siguiente código:

    define('DISABLE_WP_CRON', true);
    
  2. Agrega un trabajo cron (crontab -e en unix/linux):

    1 * * * * wget -q -O - http://example.com/wp-cron.php?doing_wp_cron
    

La primera parte (paso 1) desactivará el trabajo cron interno de WordPress. La segunda parte (paso 2) ejecutará manualmente el trabajo cron de WordPress cada minuto.

Con la respuesta de @Johano (cómo ejecutar una tarea cada 5 minutos) y la mía (cómo ejecutar manualmente el cron), deberías poder lograr tu objetivo.

5 sept 2017 07:05:52
0

Puedes activarlo durante la activación del plugin en lugar de en cada llamada al plugin:

// Añade una función de utilidad para manejar los logs de forma más limpia.
if ( ! function_exists('write_log')) {
    function write_log ( $log )  {
        if ( is_array( $log ) || is_object( $log ) ) {
            error_log( print_r( $log, true ) );
        } else {
            error_log( $log );
        }
    }
}

/**
 * No permitir que el plugin sea accedido directamente
 **/
if ( ! defined( 'ABSPATH' ) ) {
    write_log( "¡El plugin no debe ser accedido directamente!" );
    exit; // Salir si se accede directamente
}

/**
 * -----------------------------------------------------------------------------------------------------------
 * No olvides activar una llamada de sistema a la página wp-cron.php al menos cada 30 minutos.
 * De lo contrario, no podemos asegurar que el trigger será llamado.
 * -----------------------------------------------------------------------------------------------------------
 * Comando en Linux:
 * crontab -e
 * 30 * * * * wget http://<url>/wp-cron.php
 */

/**
 * Añade un horario personalizado a WordPress.
 * @param $schedules array Los horarios existentes
 *
 * @return mixed Los horarios existentes + el nuevo.
 */
function woocsp_schedules( $schedules ) {
    write_log("Creando horario personalizado.");
    if ( ! isset( $schedules["10s"] ) ) {
        $schedules["10s"] = array(
            'interval' => 10,
            'display'  => __( 'Una vez cada 10 segundos' )
        );
    }

    write_log("Horario personalizado creado.");
    return $schedules;
}

// Añade el filtro de horarios cron con el horario definido anteriormente.
add_filter( 'cron_schedules', 'woocsp_schedules' );

// Función personalizada que será llamada cuando se active el horario.
function scheduleTriggered() {
    write_log( "¡Programador activado!" );
}
add_action( 'woocsp_cron_delivery', 'scheduleTriggered' );

// Registra un hook de activación para realizar operaciones solo al activar el plugin
register_activation_hook(__FILE__, 'woocsp_activation');
function woocsp_activation() {
    write_log("Activando plugin.");

    // Activa nuestro método en el evento de horario personalizado.
    if ( ! wp_get_schedule( 'woocsp_cron_delivery' ) ) {
        wp_schedule_event( time(), '10s', 'woocsp_cron_delivery' );
    }

    write_log("Plugin activado.");
}

// Desactiva los eventos programados al desactivar el plugin.
register_deactivation_hook(__FILE__, 'woocsp_deactivation');
function woocsp_deactivation() {
    write_log("Desactivando plugin.");

    // Elimina nuestro hook programado.
    wp_clear_scheduled_hook('woocsp_cron_delivery');

    write_log("Plugin desactivado.");
}

5 mar 2018 13:05:42
1

Me temo que, aparte de esperar a que alguien visite tu sitio y ejecute una función, la única otra opción es configurar un trabajo cron en tu servidor usando algo como esto https://stackoverflow.com/questions/878600/how-to-create-cronjob-using-bash o si tienes una interfaz estilo cPanel en tu servidor, a veces hay una GUI para configurar esto.

10 nov 2015 10:55:05
Comentarios

sí..., entiendo eso... Ya tengo algunos crons creados desde cPnael... pero ahora estoy intentando ejecutar una función desde functions.php porque cuando la función está en un plugin o en functions.php no podemos pedir a los clientes que configuren un cron desde cpanel por su cuenta...

foolishcoder7721 foolishcoder7721
10 nov 2015 11:00:08
0

El plugin Programador de Cronjobs te permite ejecutar tareas frecuentes de manera confiable y puntual sin que nadie tenga que visitar tu sitio, todo lo que necesitas es al menos 1 acción y un horario Unix Crontab.

Es muy fácil de usar y muy flexible. Creas tu propia función y defines una acción dentro de ella. Luego puedes elegir tu acción desde el menú del plugin y activarla cuando quieras.

30 ene 2016 02:22:55
0

Tengo una posible solución usando una función programada y una función recursiva de WP Ajax.

  1. Crear un evento programado cada 60 minutos para ejecutar una función
  2. Esta función activará una función recursiva usando Ajax a través de file_get_contents()
  3. La función ajax tendrá un contador en la base de datos con un número total de 60 (por cada minuto dentro de la hora).
  4. Esta función ajax verificará tu contador para:

Si el contador es igual o mayor a 60, reiniciará el contador y esperará el próximo cron job.

Si el contador es múltiplo de 5 (cada 5 minutos) ejecutará tu función deseada

Y, además de las condiciones, esperará 59 segundos sleep(59); (asumiendo que tu función es rápida). Después de la espera, se activará a sí misma usando file_get_contents() nuevamente.

Cosas importantes a considerar:

  1. Crear una forma de interrumpir el proceso (ej. verificando un valor en la BD)
  2. Crear una forma de prevenir 2 procesos al mismo tiempo
  3. En file_get_contents establecer el límite de tiempo en el encabezado a 2 o 3 segundos, de lo contrario el servidor podría tener varios procesos esperando sin razón
  4. Puedes usar set_time_limit(90); para intentar evitar que el servidor detenga tu función antes del sleep

Es una solución, no la mejor, y podría ser bloqueada por el servidor. Usando un cron externo puedes configurar una función simple y el servidor usará recursos una vez cada 5 minutos. Con esta solución, el servidor estará usando recursos todo el tiempo.

10 nov 2015 14:46:52