¿Cuál es la forma correcta de limpiar archivos temporales almacenados en php?

Dec 01 2020

Estoy tratando de encontrar una manera de limpiar mi espacio de almacenamiento temporal usando php. Sé que puedo configurar trabajos cron pero, ¿hay alguna manera de hacerlo desde php?

Utilizo una carpeta de almacenamiento temporal para almacenar archivos PDF generados para que el usuario los descargue. He logrado forzar la caducidad del archivo, por lo que ya no estará disponible públicamente para acceder después de 3 minutos. Ahora el problema. Aunque el archivo no es accesible públicamente, todavía está almacenado en mi servidor. He codificado algo como esto para limpiar el almacenamiento.

/** from the main thread */
if (rand(1, 100) <= 5) {
    Reports::clean();
}

/** the clean function */
public static function clean()
{
    $path = static::getStoragePath(); if($dir_handle = opendir($path)) { while (($fileName = readdir($dir_handle)) !== false) { $file = $path . '/' . $fileName;
            
            if (!is_file($file)) continue; // If file is older that 3 minutes delete it if (time() - filemtime($file) > static::$expires) { unlink($file);
            }
        }
        closedir($dir_handle);
    }
}

así que esto limpiará el almacenamiento al azar. Sobre todo esto está bien. pero el problema es cuando la limpieza del almacenamiento comienza, ralentiza esa solicitud como una tortuga.

Entonces pensé en crear un cronjob. Pero, ¿hay una forma correcta de hacer esto desde php?

Nota: Estoy usando slim-4, tampoco tengo mucha experiencia en la configuración de cronjobs. Entonces cualquier recurso también será útil

Respuestas

3 MarcinJóźwikowski Dec 01 2020 at 17:04

Respuesta corta: no.

PHP no tiene forma de activar automáticamente ninguna acción.

Cree un script (o un comando si es un marco) y actívelo con un cronjob.

2 MarkusAO Dec 01 2020 at 17:23

En su implementación, siempre que la rutina de limpieza llegue al hilo principal, dependiendo del volumen de archivos en su directorio PDF, puede crear un retraso significativo en la respuesta.

Como se señaló en los otros comentarios / respuestas, un trabajo cron sería de hecho la forma "estándar" de manejar esto. Sin embargo, si no tiene acceso a trabajos cron, o simplemente prefiere una solución PHP pura, hay un par de enfoques posibles, además de lo que ya está haciendo.

  1. Mantenga un registro de los archivos creados junto con una marca de tiempo de creación. Cuando se llama a la rutina de limpieza, en lugar de realizar un análisis completo del directorio con verificaciones de tiempo modificadas, elimine según su registro y elimine las entradas eliminadas del registro. Almacene su registro, por ejemplo, como un archivo JSON o como CSV / TSV. Esto debería proporcionar una aceleración significativa en los casos en que hay un volumen significativo de archivos, dada la reducción en el acceso al sistema de archivos.

  2. Si no desea molestar a sus usuarios con el retraso de limpieza, mueva la rutina de los archivos de cara al usuario a archivos solo para administradores, o realice una verificación de usuario administrador y ajuste el disparador de frecuencia de limpieza (en OP con 1:20) para que coincida con la frecuencia de uso del administrador. Por supuesto, esto puede reducir la frecuencia de limpieza (si los administradores no están presentes), pero quitará la carga al público.

  3. Por último, obviamente, conviértase en Mr. Cron y active la limpieza manualmente de vez en cuando, a diario o antes de que su servidor se quede sin espacio. En general, a menos que tenga poco espacio, no parece ser necesario limpiar cada 20 páginas llamadas. No tengo idea del volumen de archivos PDF generados, el tráfico que se produce o los recursos del servidor, por lo que es difícil encontrar cifras recomendadas sobre la frecuencia de limpieza.

TomiL Dec 01 2020 at 21:55

Este es un mal concepto, use el programador cronjob para este trabajo. Aquí está bash oneliner para eliminar todos los archivos en la carpeta / tmp / some_path si el contenido de la carpeta excede los 10 MB (modifique según sus necesidades):

SIZE=$(du -bs --block-size=1M /tmp/some_path | cut -f1); if [[ $SIZE -gt 10 ]];then echo "Folder '/tmp/some_path' has size ($SIZE MB)."; rm -r /tmp/some_path/*; fi

Puede pegar este código en script.sh (incluir shebang, por ejemplo, para bash #!/bin/bashen la parte superior y hacer que el archivo sea ejecutable, por ejemplo chmod +x script.sh), luego agregar una nueva línea al programador cronjob (por ejemplo crontab -e) para verificar el tamaño de la carpeta cada hora :

0 * * * * <path_to_the_script>/script.sh

Puedes encontrar más sobre cronjobs aquí: https://crontab.guru