2012-12-19 21 views
17

Właśnie odziedziczyłem stronę ze skryptem PHP, który stale kończy się z pamięci na 117 MB. Dzieje się tak nawet wtedy, gdy zwiększam zmienną memory_limit PHP do 312 MB, co robię przez php.ini.Błąd braku pamięci PHP, mimo że nie osiągnięto limitu pamięci

Zostało to teraz rozwiązane dzięki świetnej informacji z pcguru. Zobacz moją odpowiedź poniżej, który zaczyna się: I w końcu znalazłem odpowiedź

ini_get('memory_limit') zwraca wartość ustawioną w php.ini, więc jestem pewien Apache został uruchomiony ponownie po zmianie wartości. Używam memory_get_usage(true), aby zwrócić pamięć zużywaną przez skrypt w różnych punktach po drodze. Konsekwentnie kończy się niepowodzeniem, gdy osiągnie 117 MB.

Czy jest jakiś wewnętrzny limit PHP, o którym nie mam pojęcia, czy nigdy nie przydzieli on więcej niż 117 MB do pojedynczego skryptu?

Serwer ma 1 GB pamięci RAM i działa w systemie CentOS. Mam dostęp do powłoki głównej. PHP jest w wersji 5.3.18. MySQL to wersja 5.1.66-cll.

Ten skrypt znajduje się za nazwą użytkownika/hasłem i nie mogę zapewnić publicznego dostępu do niego.

Edytowane do dodania:

1) Dzięki wszystkim za pomoc do tej pory. Więcej informacji znajdziesz w moich odpowiedziach na komentarze użytkowników w różnych odpowiedziach poniżej.

2) Suhosin zdecydowanie nie jest zainstalowany. Sprawdziłem wiele miejsc, w tym uruchomiłem skrypt i sprawdziłem stałe i uruchomiłem php -v

3) Dziennik apache nie ma zapisów konkretnego komunikatu o błędzie, który dostaję. Rejestrowanie jest włączone w php.ini. Przeszedłem przez grep, żeby przeszukać cały dziennik.

4) Czy w tym przypadku jest zgłaszany błąd?

+9

Czym dokładnie jest błąd, który widzisz? Być może jesteś zdezorientowany przez "próbę przydzielenia xxx bajtów" –

+4

Kudos za posiadanie aktualnej wersji PHP 5.3. –

+2

Czy masz łatkę suhosin przez przypadek? – DaveRandom

Odpowiedz

17

W końcu znalazłem odpowiedź. Wskazówki pochodziły z odpowiedzi od pcguru: "Ponieważ serwer ma tylko 1 GB pamięci RAM ...".

Podejrzałem, czy Apache ma własne limity pamięci, ponieważ mogą one wpływać na zdolność PHP do przydzielania pamięci. Na samym początku httpd.conf znalazłem to stwierdzenie: RLimitMEM 204535125

Zostało to wprowadzone przez whm/cpanel. Zgodnie z następującym strona WHM/cPanel niepoprawnie oblicza jego wartość na serwerze wirtualnym ... http://forums.jaguarpc.com/vps-dedicated/17341-apache-memory-limit-rlimitmem.html

Skrypt że zabraknie pamięci dostaje większość drogi przez, więc zwiększona RLimitMEM do 268435456 (256 MB) i powtórzyć scenariusz. Ukończył scalanie tablic i wygenerował plik csv do pobrania.

ETA: Po dokładniejszym zapoznaniu się z RLimitMEM i RLimitCPU postanowiłem usunąć je z httpd.conf. Pozwala to na działanie ini_set ('memory_limit', '### M'), a teraz daję temu skryptowi dodatkową pamięć, której potrzebuje. Podwajałem również pamięć RAM na tym serwerze.

Dziękuję wszystkim za pomoc w wykryciu tego ciernistego problemu, a szczególnie w przypadku pcguru, który wymyślił ważną wskazówkę, która doprowadziła mnie do rozwiązania.

1

To nie może być odpowiedź na twój problem, ale jeśli uruchomisz PHP z wiersza poleceń, możesz przekroczyć limit pamięci ze strony php.ini.

php -d memory_limit=321M my_script.php 

Nie jestem do końca pewien, jaki jest domyślny limit pamięci przez cli. Można również uruchomić php --ini i sprawdzić wyniki.

+0

php --ini zwraca: Plik konfiguracyjny (php.ini) Ścieżka:/usr/local/lib Załadowany plik konfiguracyjny: /usr/local/lib/php.ini Zeskanuj dodatkowe pliki .ini w: (brak) Dodatkowe pliki .ini zostały przeanalizowane: (brak) – user8109

+0

Ponadto - nie mogę uruchomić skryptu z monitu, ponieważ część, która ulega awarii, wymaga kilku zmiennych postu. Niestety jest to dość skomplikowane, używając ogromnych tablic z powodów, które nie mają dla mnie sensu. Moim zdaniem powinno to być używanie tabel tymczasowych i wysyłanie wyniku końcowego do PHP. Ale w międzyczasie, jeśli mogę dać mu 198 MB, zostanie ukończone, co jest użyteczną chwilową poprawką. – user8109

+0

Zrozum to. Naprawdę dziwne zachowanie. – aebersold

-5

Masz nieskończoną pętlę gdzieś w kodzie.

+2

Jak możesz to powiedzieć bez patrzenia na kod. Jest to najlepsze przypuszczenie, które nie powinno być publikowane jako odpowiedź. – webnoob

+0

Jeśli podniesienie limitu pamięci nie pomoże, jest to drugie zjawisko, które może spowodować ten typ błędu. Każdy może spróbować tego z nieskończoną pętlą lub złą funkcją rekursji. –

+0

To nie jest nieskończona pętla. To wymagałoby nieskończonej tablicy! Konsekwentnie ulega awarii przy 117 MB, pomimo (podobno) posiadania większej dostępnej pamięci RAM. Co więcej, pętla, w której występuje awaria, dokonuje scalenia tablicy. Każda iteracja skubie około 79 bajtów. – user8109

2

To nie jest odpowiedź na pytanie, dlaczego skrypt umiera po pewnym zużycie pamięci, ale można obejść poprzez usunięcie limitu pamięci całkowicie wewnątrz skryptu PHP samego:

ini_set('memory_limit', '-1'); 

To jest niebezpieczny. Jeśli masz uciekający skrypt, PHP zajmie pamięć do czasu, aż serwer nie pozostanie do przydzielenia i przewróci się. Dlatego powinieneś używać tego tylko wtedy, gdy jesteś pewien, że sam skrypt nie stanowi problemu i tylko po to, aby przetestować wyjście.

Co do tego, czy PHP ma jakiś limit na wykorzystanie pamięci, nie. Osobiście uruchamiam skrypty zużywające prawie 1 GB pamięci.

+0

Dzięki M_user. Nie mogę ryzykować, że zabiorę bloga w PHP. Strony klientów są dostępne na całym świecie, więc nie ma dogodnego przestoju. Przydatne wiedzieć, że PHP nie narzuca limitu - dzięki za to. Czy jest możliwe, że błąd jest zgłaszany przez pomyłkę? – user8109

+0

Wszystko jest możliwe. Jaki był faktyczny komunikat o błędzie? –

8

Ponieważ serwer ma tylko 1 GB pamięci RAM, pochylam się do możliwości całkowitego wyczerpania pamięci systemowej.

See this thread. Otrzymujesz ten sam "Błąd krytyczny PHP: brak pamięci" zamiast bardziej powszechnego "Błąd krytyczny: Dozwolony rozmiar pamięci ...". Twój błąd oznacza, że ​​system nie może w ogóle przydzielić więcej pamięci, co oznacza, że ​​nawet wewnętrzne funkcje PHP nie mogą przydzielić więcej pamięci, nie mówiąc już o własnym kodzie.

W jaki sposób PHP jest skonfigurowane do pracy z Apache? Jako moduł lub jako CGI? Ile procesów PHP można uruchomić w tym samym czasie? Czy masz dostępną przestrzeń wymiany?

Jeśli używasz PHP jako modułu w Apache, Apache ma nieprzyjemny zwyczaj utrzymywania pamięci, którą przydzielono procesowi PHP. Zgadywanie, ponieważ nie może ponownie uruchomić modułu PHP w module roboczym, wystarczy całkowicie zrestartować moduł roboczy. Każdy pracownik, który obsługiwał PHP, po prostu powiększa się do limitu pamięci PHP w czasie, ponieważ ten robot obsługuje skrypt, który przydziela dużo pamięci RAM. Więc jeśli masz wielu pracowników w tym samym czasie, każdy używający 100 MB +, szybko zabraknie pamięci RAM. Spróbuj ograniczyć liczbę równoczesnych pracowników w Apache.

+0

Dzięki pcguru - to ma sens i pasuje do faktów. Aby odpowiedzieć na twoje pytania: PHP jest uruchamiane jako moduł. Dostępna jest przestrzeń wymiany i jest używana - jest to wirtualny serwer z 8 stronami. Istnieją duże tabele DB - największe ma 2,4 miliona rekordów.Istnieje wiele osób odwiedzających witrynę, a ten raport jest jednym z kilkudziesięciu swoich pracowników. Wyjaśnienia odpowiadają również na kolejne zagadki, dlatego też raport zakończył się sukcesem w małych godzinach poprzedzających (kiedy myślałem, że naprawiłem problem :-). Zaraz zobaczę, jak biegnie z góry w innym oknie. – user8109

+0

Uruchamianie top pokazuje, że system nie wyczerpał fizycznej pamięci RAM podczas wykonywania kwerendy. Upadło do około 60 MB tuż przed awarią, ale wciąż posiadało 1,6GB przestrzeni wymiany. To była świetna sugestia i być może doprowadziło mnie to do rzeczywistej odpowiedzi, więc dziękuję za to. Właśnie testuję teraz. – user8109

+1

Dobrze to słyszeć, istnieją sposoby na zmniejszenie użycia pamięci w Apache/PHP, ale generalnie jest to wynikiem niższej wydajności. Mam nadzieję, że to działa. W przeciwnym razie zawsze można kupić więcej pamięci RAM dla serwera. :) – oldwizard

Powiązane problemy