2010-08-25 114 views
6

Tengo un script php que debe ejecutarse una vez cada 5 minutos. Actualmente estoy usando un trabajo cron para ejecutarlo (y funciona muy bien) pero mi host solo permite un tiempo mínimo de 15 minutos.Ejecutar un script PHP cada 5 minutos y evitar las condiciones de carrera

Así que mi pregunta es, ¿puedo utilizar los visitantes para activar la ejecución de un script php cada 5 minutos. Puedo simplemente registrar la última vez que se ejecutó y volver a ejecutarla según el tiempo transcurrido.

Sin embargo, estoy preocupado por las condiciones de carrera. Es importante que el script solo se ejecute una vez cada 5 minutos.

Mi script tarda unos 60 segundos en ejecutarse. Escribe en un par de archivos durante este tiempo. Si el script se ejecutó más de una vez, se dañarían los archivos. Además, si no recibo visitas durante 10 minutos, ejecutar una vez cuando llegue el próximo visitante está bien.

¿Hay alguna manera estándar de llevar a cabo esta tarea?

Gracias!

+0

No estoy seguro de entender el problema. ¿Es que su host no permite que los trabajos cron se ejecuten con más frecuencia que cada 15 minutos? – Icode4food

+1

La forma estándar sería usar un host web que no imponga reglas malas y arbitrarias en cron. ¿Quién demonios hace esto? – Erik

+1

Switch hosts. Problema resuelto – Stoosh

Respuesta

6

¿Ha considerado simplemente hacer que su script ejecute un ciclo infinito con sleep para esperar 5 minutos entre iteraciones?

for (;;) 
{ 
    perform_actions(); 
    sleep(300); 
} 

Alternativamente, usted podría tener un archivo (por ejemplo, is_running), y obtener una exclusiva lock en él al comienzo de la secuencia de comandos que se libera al final. Al menos de esta manera no harás nada destructivo.

También podría combinar estas dos soluciones.

$fp = fopen("is_running", "r+"); 

/* is it already running? */ 
if (! flock($fp, LOCK_EX | LOCK_NB)) return; 

for (;;) 
{ 
    perform_actions(); 
    sleep(300); 
} 

Y luego haga que la tarea cron se ejecute cada 15 minutos. Si el proceso todavía se está ejecutando, simplemente se rescatará, de lo contrario se reiniciará y reanudará la actualización cada 5 minutos.

+0

Parece una buena idea y una buena solución. Supongo que necesito llamar a set_time_limit de php. Y luego espero que mi anfitrión no mate automáticamente los procesos de larga ejecución ... Aún así, esta parece ser mi mejor apuesta. Gracias. – Imbue

+1

'set_time_limit' es la función que necesita para ajustar el tiempo de espera. http://php.net/manual/en/function.set-time-limit.php Lo pondría en algo así como 330 cada vez que se ejecuta el script para que no tenga que preocuparse. – Icode4food

+1

Solo para que sepan, el anfitrión permitió que mi script se ejecutara durante aprox. 26 horas antes de matarlo. Poco después, cron apareció en otro que notó que el archivo estaba desbloqueado y yo estaba de vuelta en el negocio. Una cosa que me asusta es lo que sucedería si el host mata mi script mientras está escribiendo datos. En ese caso, los datos podrían corromperse hasta que cron tenga la oportunidad de ejecutar otro script. En otras palabras, algunas veces al año probablemente estaría sirviendo datos corruptos durante unos 5-10 minutos. – Imbue

1

Si no puede hacer lo que @Brandon sugirió, recomendaría acercarse a esto de la misma manera que lo hice cuando escribía un daemon en PHP (no la mejor solución, pero prácticamente me forzaron a hacerlo).

En mi caso, la secuencia de comandos accedió a un archivo (log) e hizo el procesamiento en él, luego insertando los resultados en la base de datos. Entonces, para asegurarme de que no tengo dos archivos ejecutándose al mismo tiempo, creé un archivo de "estado" en el cual el script adquirió un bloqueo y si no puede hacerlo si falla correctamente.

$fh = fopen('status_file', 'w'); 

/** 
* LOCK_NB is required because otherwise your script would stall until 
* a lock is aquired, queing a bunch of scripts. 
*/ 
if(!flock($fh, LOCK_EX | LOCK_NB)) { 
    exit 1; // our job is done here 
} 
4

Lame responde por una situación coja (el ISP, no el póster). Programe 12 trabajos cron, todos llamando al mismo script, cada uno ejecutando una vez por hora, pero llamando a una marca diferente de 5 minutos.

00 * * * * root echo "run at :00 of every hour" 
05 * * * * root echo "run at :05 of every hour" 
10 * * * * root echo "run at :10 of every hour" 

etc hasta: 55. Pero mantengo mi comentario original - encuentre un nuevo ISP :)

+1

Estoy seguro de que esto funcionaría, y probablemente sea una solución decente, pero tengo miedo de lo que sucedería si mi anfitrión lo notara. – Imbue

+3

@Imbue - ¿Entonces crees que tu anfitrión miraría con más amabilidad un ciclo infinito? –

+0

Creo que un bucle infinito que pasa casi todo el tiempo en el sueño sería menos notable, y tal vez un poco menos desafiante. O no. Es difícil de decir realmente. – Imbue

0

Puede usar The Fat Controller para ejecutar un script a intervalos de 5 minutos. A diferencia de CRON, garantiza el intervalo desde el momento en que termina una instancia de la secuencia de comandos hasta cuando se inicia otra.

+0

Hola, envié un comentario a su sitio web preguntando sobre TheFatController mi nombre es 'geocine' –

0

La respuesta a si los visitantes pueden iniciar este script es sí. Puede ejecutar el script cuando los visitantes ingresen a una página. Desea almacenar la hora de inicio, pero también un atributo para si se está ejecutando. Esto debería evitar cualquier posibilidad de conflicto al tratar de actualizar sus datos.También pondré un campo adicional para la advertencia de correo electrónico que puede usar si el tiempo de ejecución supera lo que esperaría más allá del tiempo máximo. A continuación, puede hacer que el script le envíe un correo electrónico de advertencia indicando que su script se ha estado ejecutando más allá del tiempo máximo. Personalmente, he mantenido estos estados en las bases de datos, pero también se pueden almacenar en archivos.

Cuestiones relacionadas