2012-08-29 9 views
5

Szukam rozwiązania Potrzebuję usunąć pliki dziennika, ale może istnieć możliwość, że są one dostępne w momencie wywołania usunięcia. Przez dostęp, mam na myśli proces jest albo czytanie lub zapisywanie do pliku. W takich przypadkach muszę pominąć plik zamiast go usunąć. Również mój serwer to Linux i PHP działa na Apache.Usuń plik, jeśli aktualnie nie jest dostępny

Co szukam jest coś podobnego do (in pseudo-code):

<?php 
$path = "path_to_log_file"; 
$log_file = "app.log"; 
if(!being_accessed($log_file)) 
{ 
    unlink($path.$log_file); 
} 
?> 

Teraz moje pytanie jest w jaki sposób można zdefiniować being_accessed? Wiem, że może nie być funkcja języka do tego bezpośrednio w PHP. Myślę o użyciu kombinacji sekcjach jak last_access_time (może?) I flock (ale ten jest przydatny tylko w tych warunkach, gdzie plik został flock -ED przez aplikację uzyskującego dostęp)

Wszelkie sugestie/spostrzeżenia mile widziane ...

+0

jak zdefiniować plik "dostęp"? –

+0

Może to być proces albo go czytający, albo zapisujący go. –

+1

nie ma znaczenia na Linuksie, pliki nie zostaną faktycznie usunięte dopóki wszystkie wskaźniki plików do niego nie zostaną zamknięte. – SirDarius

Odpowiedz

6

Zwykle nie będziesz w stanie tego znaleźć bez uprawnień administracyjnych (i np. Możesz uruchamiać narzędzia takie jak lsof, aby sprawdzić, czy Twój plik jest wymieniony, ale jeśli twoje skrypty działają na serwerze Linux/Unix (co ma miejsce w przypadku większości hosterów), nie musisz się tym przejmować, ponieważ system plików się tym zajmie, więc na przykład masz plik 1GB i ktoś pobiera ten plik. Bezpiecznie jest usunąć plik (z unlink() lub w jakikolwiek inny sposób) zdarzenie, jeśli ten downloader właśnie się rozpoczął i nie będzie zakłócać jego pobierania, ponieważ system plików wie, że plik jest już otwarty (niektóre procesy posiadają uchwyt), więc będzie go tylko oznaczać, powiedzmy invisible dla innych (więc raz spróbujesz wyświetlić zawartość folderu, której już nie zobaczysz, ale jeśli twój plik jest wystarczająco duży, możesz spróbować sprawdzić dostępne miejsce na dysku (np. z df, aby zobaczyć, że nadal będzie zajęty)), ale te, jak utrzymywał uchwyt nadal będzie mógł z niego korzystać. Gdy wszystkie procesy zostaną zamknięte, ich plik uchwytu zostanie fizycznie usunięty z nośnika, a przestrzeń dyskowa zwolniona. Po prostu odłącz w razie potrzeby. Jeśli martwić o ostrzeżenie unlink może rzucać (co może się zdarzyć w systemie Windows), a następnie po prostu poprzedzić wezwanie z @ znaku (@unlink()), aby wyłączyć żadnego ostrzeżenia to wezwanie może rzucać się w czasie wykonywania

+0

Czy usuwanie będzie w takich przypadkach blokowaniem? Tak jak w przypadku, gdy proces zapisuje do niego w pętli i istnieje wywołanie delete przeciwko niemu. Czy blok zostanie usunięty, dopóki proces zapisu się nie zakończy? –

+1

"Odłączenie" zostanie natychmiast zwrócone, tak jakby nikt nie używał tego pliku. –

+0

Brzmi doskonale do tego, co robię, dzięki! –

1

Można by po prostu zmienić swój kod w ten sposób (jeśli robisz to powtarzalnie):

<?php 
$path = "path_to_log_file"; 
$log_file = "app.log"; 
@unlink($path.$log_file); 

Zawiadomienie @, aby uniknąć błędu w przypadku, gdy plik nie jest usuwalnego, a brak kończąc tag (kończące znaczniki są źródłem częstych błędów i powinny należy unikać)