Как правильно очистить сохраненные временные файлы на php?

Dec 01 2020

Я пытаюсь найти способ очистить свое временное хранилище с помощью php. Я знаю, что могу настроить задания cron, но есть ли способ сделать это из самого php?

Я использую папку временного хранения для хранения сгенерированных PDF-файлов для загрузки пользователем. Мне удалось принудительно установить срок действия файла, чтобы он больше не был доступен для публичного доступа через 3 минуты. Теперь о проблеме. Хотя файл недоступен для всех, он все еще хранится на моем сервере. Я закодировал что-то подобное, чтобы очистить хранилище.

/** 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);
    }
}

так что это очистит хранилище случайным образом. В основном это нормально. но проблема в том, что когда начинается очистка хранилища, это замедляет этот запрос, как черепаха.

Итак, я подумал о создании cronjob. Но есть ли правильный способ сделать это из самого php?

Примечание: я использую slim-4, также не имею большого опыта в настройке cronjobs. Так что любой ресурс тоже будет полезен

Ответы

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

Короткий ответ: нет.

PHP не имеет возможности самостоятельно запускать какие-либо действия.

Создайте сценарий (или команду, если это фреймворк) и активируйте его с помощью cronjob.

2 MarkusAO Dec 01 2020 at 17:23

В вашей реализации всякий раз, когда процедура очистки попадает в основной поток, в зависимости от объема файлов в вашем каталоге PDF, это может вызвать значительную задержку в ответе.

Как отмечалось в других комментариях / ответах, задание cron действительно было бы «стандартным» способом справиться с этим. Однако, если у вас нет доступа к заданиям cron или вы просто предпочитаете чистое PHP-решение, есть несколько возможных подходов, помимо того, что вы уже делаете.

  1. Ведите журнал созданных файлов вместе с отметкой времени создания. Когда вызывается процедура очистки, вместо выполнения полного сканирования каталога с измененными проверками времени удалите на основе вашей записи и удалите удаленные записи из записи. Сохраните свою запись, например, как файл JSON или как CSV / TSV. Это должно обеспечить значительное ускорение в случаях, когда имеется значительный объем файлов, учитывая сокращение доступа к файловой системе.

  2. Если вы не хотите беспокоить пользователей задержкой очистки, переместите процедуру из файлов, предназначенных для пользователей, в файлы, предназначенные только для администратора, или выполните проверку пользователя с правами администратора и настройте триггер частоты очистки (в OP с 1:20), чтобы соответствовать частоте использования администратора. Это, конечно, может уменьшить частоту очистки (если администраторов нет рядом), но снимет нагрузку с публики.

  3. Наконец, очевидно, станьте мистером Кроном и запускайте очистку вручную время от времени, ежедневно или до того, как на вашем сервере закончится место. В общем, если у вас не очень мало места, нет необходимости очищать каждые 20 вызовов страниц или около того. Я не имею представления об объеме сгенерированных PDF-файлов, трафике или ресурсах сервера, поэтому трудно дать рекомендуемые цифры по частоте очистки.

TomiL Dec 01 2020 at 21:55

Это плохая концепция, используйте для этой работы планировщик cronjob . Вот bash oneliner для удаления всех файлов в папке / tmp / some_path, если содержимое папки превышает 10 МБ (пожалуйста, измените в соответствии с вашими потребностями):

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

Вы можете вставить этот код в script.sh (включить shebang, например, для bash #!/bin/bashвверху и сделать файл исполняемым, например. chmod +x script.sh), Затем добавить новую строку в планировщик cronjob (например crontab -e), чтобы проверять размер папки каждый час :

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

Вы можете найти больше о cronjobs здесь: https://crontab.guru