Autonomía digital y tecnológica

Código e ideas para una internet distribuida

Cómo ejecutar PHP periódicamente con cron en un servidor Linux

Imago voragine.net
[actualizado el ]

Primero tenemos que tener la posibilidad de ejecutar un script PHP desde la línea de comandos, o en su defecto ejecutarlo con curl; en este tutorial lo haremos ejecutando el PHP directamente en la línea de comandos sin curl. Luego tenemos que generar el archivo PHP, y un script sh que ejecute el script PHP. Por último, configuraremos cron para que ejecute el script de bash con la periodicidad que necesitemos.

Para ejecutar un script PHP en la línea de comandos necesitamos tener instalado el paquete php5-cli, como root.

apt-get install php5-cli

La sintaxis para ejecutar un script PHP es la siguiente:

php file.php

Generamos un script PHP mínimo, que escribirá una línea en un archivo de texto plano cada vez que se ejecute, y lo llamamos por ejemplo test.cron.php; el archivo se alojará en el mismo directorio que los scripts.

$time = date("G:i:s");
$entry = "Información guardada a las $time.\n";
$file = "/var/www/testdir/test.cron.txt";
$open = fopen($file,"a");

if ( $open ) {
	fwrite($open,$entry);
	fclose($open);
}

Para que al ejecutar el script con cron no nos dé el error Could not open input file: test.cron.php, es recomendable especificar la ruta completa al archivo PHP. Si el error que obtenemos está relacionado con open_basedir restriction tenemos que definir la variable open_basedir en el archivo /etc/php5/cli/php.ini y asignarle como valor la ruta del directorio donde se encuentre el script PHP, como root, importante el punto final:

open_basedir = /var/www/testdir/.

Luego reiniciamos el servidor apache, como root:

service apache2 restart

Creamos ahora un script de bash que ejecute el script PHP; lo llamamos por ejemplo test.cron.sh:

#!/bin/sh
php /var/www/testdir/test.cron.php

Es importante la primera línea que le dice al sistema el tipo de shell que debe usar para ejecutar el script. La shell tiene que ser la misma que almacena la variable SHELL del archivo /etc/crontab, /bin/sh en mi caso.

Por último, configuramos cron, tras asegurarnos de que el demonio crond está corriendo. Básicamente necesitamos decirle a cron qué script queremos ejecutar y con qué periodicidad. Podemos hacerlo editando el archivo /etc/crontab, añadiéndole la siguiente línea, a continuación de las reglas ya existentes, como root:

*/15 * * * * usuario /var/www/testdir/./test.cron.sh

En este caso, el script /var/www/testdir/./test.cron.sh se ejecutará cada quince minutos. Es importante que el usuario tenga suficientes permisos para leer y ejecutar el script.

Actualización 2 octubre 2013. Para añadir una tarea a cron sin permisos de usuario root podemos usar la orden crontab -e en la línea de comandos.

20 comentarios

    • Por German •

    Como veo en un log el error… o porque no me funciona?

  1. Hola German, cuando cron genera un log que envía por correo interno del localhost al usuario al que pertenece el proceso cronificado, siempre que tengas instalado un servidor de correo.

    Para saber por qué no te funciona, necesito más datos. El fallo más común está en una mala definición del path del script que se quiere cronificar: compruebalo.

    También puede ser que el script no tenga permisos de ejecución. Para comprobar que los tiene usa ls -l en la carpeta donde lo tengas alojado.

    Otra razón puede ser que el script tenga algún fallo de sintaxis que impida su ejecución. Para comprobar ejecuta el script a mano con el comando ./nombre.script.sh desde la carpeta en la que lo tengas alojado.

    • Por jamzzz

    hola, como hago para cambiar los minutos por segundos?

    1. Hola jamzzz,

      el intervalo mínimo de cron para configurar la frecuencia de ejecución de una tarea es un minuto. No se puede ejecutar una tarea cada x segundos. Más info.

    • Por T.T.os •

    Gracias!

    • Por Alberto

    Una pregunta, el archivo .sh se debe localizar en la misma carpeta que el archivo php a ejecutar o donde lo pongo?, Gracias Excelente explicacion

    1. Hola Alberto,

      puedes alojar el archivo sh donde quieras, no tiene por qué estar en la misma carpeta que el php. Asegúrate de incluir en el archivo sh la ruta correcta y absoluta al archivo php; y en crontab la ruta correcta y absoluta al archivo sh.

    • Por Julio •

    open_basedir = /var/www/testdir/.

    Todo se ve bien, pero no encuentro explicacion al punto final. Para qué?
    En el script dice «importante el punto final», pero no se explica por qué? Y el link tampoco lo hace.
    Saludos

  2. Hola Julio,

    el punto en UNIX y Linux indica «directorio actual», como .. (punto punto) indica directorio superior en el árbol de directorios.

    /var/www/testdir/. indica que el directorio base es testdir inequivocamente. /var/www/testdir podría ser un archivo, por eso no funciona sin el punto.

  3. Gracias por el aporte, me hacía falta crear un cron y ha sido de mucha utilidad. Un saludo.

    • Por carlos munoz •

    Buen post, quisiera saber si es posible mediante cron, modificar un documento php o html cada cierto tiempo, ejemplo:
    Poseo un sitio web, y en el index, cada día a primera hora cargo manualmente al rededor de 20 eventos, cada uno en una hora distinta, estos eventos son unas tareas o pequeños ejercicios para mis alumnos, cada uno de estos ejercicios, que los he llamado ‘eventos’, tienen una diferencia de 1 hora aproximadamente, el primero comienza a las 8 am, y así sucesivamente hasta la noche, obviamente cada tarea o ejercicio tiene una variable que contiene su hora de inicio y de fin,, mi pregunta sería !..podría automatizar mediante cron la inhabilitación de cada uno de los eventos o ejercicios en función de su hora ?
    Ejemplo si un ejercicio tiene como hora de caducidad 9:00 am, que a esa hora mediante cron, pueda quedar inhabilitada?
    Muchas gracias de antemano, me gustaría saber si este u otro método sería posible.

    1. Hola Carlos,

      si entiendo bien lo que quieres hacer, no necesitas cron. Puedes hacerlo todo con PHP. El código de cada evento lo puedes asociar a una sentencia condicional, de manera que solo se ejecute en un intervalo de tiempo determinado. Defines el intervalo de tiempo en UNIX timestamp y lo comparas en la sentencia con la hora actual.

        • Por carlos •

        Muchas gracias por la idea amigo, cuando lo aplique, quiza comente otra vez por aqui, saludos

  4. muchas gracias hermano, me ha sido de mucha utilidad. sigue así :)

    • Por felipe •

    hola, muy buen tuto, pero me da un error, lo estoy probando en centos y con php 5 y me da un warnign «PHP Warning: PHP Startup: Unable to load dynamic library ‘/usr/lib64/php/modules/php_openssl.dll’ – /usr/lib64/php/modules/php_openssl.dll: cannot open shared object file: No such file or directory in Unknown on line 0»
    y luego el script no hace nada, si me puedes ayudar, gracias

    1. Hola Felipe,

      ¿has probado a ejecutar el script PHP manualmente? Puede hacerlo en la línea de comandos: php file.php.

      Si eso tampoco funciona el problema está en el script y no necesariamente en la configuración de cron.

        • Por jctribin •

        Felipe lo pudiste solucionar?

    • Por Luis Javier García •

    Muchas gracias por el aporte, también es importante señalar que los include se deben realizar a una ruta absoluta

Dejar un comentario

*
*

 

2 trackbacks