Jaki jest właściwy sposób czyszczenia przechowywanych plików tymczasowych w php?

Dec 01 2020

Próbuję znaleźć sposób na wyczyszczenie mojej tymczasowej przestrzeni dyskowej za pomocą php. Wiem, że mogę skonfigurować zadania cron, ale czy jest sposób, aby to zrobić z samego php?

Używam folderu tymczasowego przechowywania do przechowywania wygenerowanych plików PDF do pobrania przez użytkownika. Udało mi się wymusić wygaśnięcie pliku, więc po 3 minutach nie będzie już publicznie dostępny. Teraz problem. Chociaż plik nie jest dostępny publicznie, nadal jest przechowywany na moim serwerze. Zakodowałem coś takiego, aby wyczyścić pamięć.

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

więc spowoduje to losowe czyszczenie pamięci. W większości jest to w porządku. ale problem polega na tym, że czyszczenie magazynu zaczyna tak spowalniać żądanie jak żółw.

Pomyślałem więc o stworzeniu cronjob. Ale czy istnieje właściwy sposób na zrobienie tego z samego php?

Uwaga: używam slim-4, również nie mam dużego doświadczenia w konfigurowaniu cronjobs. Więc każdy zasób również będzie pomocny

Odpowiedzi

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

Krótka odpowiedź: nie.

PHP nie ma możliwości samoczynnego wyzwalania jakichkolwiek działań.

Utwórz skrypt (lub polecenie, jeśli jest to framework) i uruchom go za pomocą cronjob.

2 MarkusAO Dec 01 2020 at 17:23

W Twojej implementacji za każdym razem, gdy procedura czyszczenia trafia do głównego wątku, w zależności od ilości plików w katalogu PDF, może to spowodować znaczne opóźnienie w odpowiedzi.

Jak zauważono w innych komentarzach / odpowiedziach, zadanie cron byłoby rzeczywiście „standardowym” sposobem radzenia sobie z tym. Jeśli jednak nie masz dostępu do zadań crona lub po prostu wolisz czyste rozwiązanie PHP, istnieje kilka możliwych podejść, poza tym, co już robisz.

  1. Prowadź dziennik utworzonych plików wraz z sygnaturą czasową utworzenia. Gdy wywoływana jest procedura czyszczenia, zamiast przeprowadzać pełne skanowanie katalogu ze zmodyfikowanym sprawdzaniem czasu, usuń na podstawie rekordu i usuń usunięte wpisy z rekordu. Zapisz swój rekord, np. Jako plik JSON lub jako CSV / TSV. Powinno to zapewnić znaczne przyspieszenie w przypadkach, gdy istnieje znaczna ilość plików, biorąc pod uwagę ograniczenie dostępu do systemu plików.

  2. Jeśli nie chcesz przeszkadzać użytkownikom opóźnieniem czyszczenia, przenieś procedurę z plików widocznych dla użytkownika do plików tylko dla administratora lub przeprowadź kontrolę administratora i dostosuj wyzwalacz częstotliwości czyszczenia (w OP za pomocą 1:20), aby dopasować częstotliwość użytkowania przez administratora. Może to oczywiście zmniejszyć częstotliwość czyszczenia (jeśli administratorów nie ma w pobliżu), ale odciąży społeczeństwo.

  3. Wreszcie, oczywiście, zostań Panem Cronem i uruchamiaj czyszczenie ręcznie raz na jakiś czas, codziennie lub zanim na serwerze zabraknie miejsca. Ogólnie rzecz biorąc, jeśli nie masz bardzo mało miejsca, czyszczenie co 20 wywołań stron nie jest konieczne. Nie mam pojęcia o ilości generowanych plików PDF, natężeniu ruchu lub zasobach serwera, więc trudno jest podać zalecane dane dotyczące częstotliwości czyszczenia.

TomiL Dec 01 2020 at 21:55

To zła koncepcja, użyj harmonogramu cronjob do tego zadania. Oto bash oneliner do usuwania wszystkich plików w folderze / tmp / some_path, jeśli zawartość folderu przekracza 10 MB (zmodyfikuj odpowiednio do swoich potrzeb):

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

Można obok tego kodu do script.sh (m.in. shebang np bash. #!/bin/bashNa górze i make pliku wykonywalnego tj. chmod +x script.sh), Następnie dołączyć nową linię do planującego cron (np crontab -e), aby sprawdzić rozmiar folderu co godzinę :

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

Więcej o cronjobs można znaleźć tutaj: https://crontab.guru