Apache-2.2

Allowed Memory Size 用盡,不管數量,記憶體洩漏?

  • July 5, 2015

我在一個非常常見的 CentOS 5.11 與 Apache 2 和 PHP 5.3.3 上為我的妹妹執行一個小型 Wordpress 部落格。

最近,我們發現當她嘗試使用 Wordpress 自己的界面更新或安裝任何東西時,一切都停止了,我發現了這個:

PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 20 bytes) in /var/www/foobar/wp-admin/includes/file.php on line 159, referer: http://foobar.com/wp-admin/update-core.php?action=do-core-upgrade

在搜尋了一下之後,最簡單的事情似乎就是稍微提高記憶體限制,但不管我將它提高到多少,它基本上只需要更長的時間才能達到這個屋頂。

以下是一些摘錄:

512M

PHP Fatal error:  Allowed memory size of 536870912 bytes exhausted (tried to allocate 261900 bytes) in /var/www/foobar/wp-admin/includes/file.php on line 159, referer: http://foobar.com/wp-admin/update-core.php?action=do-core-upgrade

1024M

PHP Fatal error:  Allowed memory size of 1073741824 bytes exhausted (tried to allocate 261900 bytes) in /var/www/foobar/wp-admin/includes/file.php on line 159, referer: http://foobar.com/wp-admin/update-core.php?action=do-core-upgrade

這一切都是使用…配置的

memory_limit = 1024M

在 /etc/php.ini 以及…

define('WP_MEMORY_LIMIT', '1024M');
           } else {
                   define('WP_MEMORY_LIMIT', '1024M');
           }
   }

   if ( ! defined( 'WP_MAX_MEMORY_LIMIT' ) ) {
           define( 'WP_MAX_MEMORY_LIMIT', '1024M' );
   }

在 ~/wp-includes/default-constants.php 中。

這顯然讓我相信某個地方存在必須解決的記憶體洩漏,但是當所有東西都是預先打包的 Wordpress 東西時,我將如何找到它呢?以下是按下更新按鈕時頂部 ^M的一些摘錄:

Mem:   1034656k total,   235836k used,   798820k free,     6388k buffers
Swap:  2048248k total,   107940k used,  1940308k free,   139156k cached

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
23649 apache    19   0  160m  22m  15m S  0.0  2.2   0:07.06 httpd

儘管

Mem:   1034656k total,  1020396k used,    14260k free,       60k buffers
Swap:  2048248k total,   152484k used,  1895764k free,    26880k cached

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
23645 apache    21   0 1079m 906m  16m R 75.5 89.7   0:06.95 httpd

WordPress 版本 4.2

MySQL 5.1

阿帕奇 2.2.22

已安裝外掛:Hello Dolly 1.6 和 Akismet 3.1.1


這是strace -f -r的輸出,正是它停止的地方:

29638 0.000134 writev(16, [{"28\r\n", 4}, {"<p>Enabling Maintenance modeR"..., 40}, {"\r\n", 2}], 3) = 46 29638 0.000122 time(NULL) = 1436025429 29638 0.000060 getcwd("/var/www/foobar/wp-admin"..., 4096) = 32 29638 0.000064 time(NULL) = 1436025429 29638 0.000040 open("/tmp/php9Ldioo", O_RDWR|O_CREAT|O_EXCL, 0600) = 19 29638 0.000061 getpeername(18, {sa_family=AF_INET, sin_port=htons(21), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0 29638 0.000068 poll([{fd=18, events=POLLOUT}], 1, 240000) = 1 ([{fd=18, revents=POLLOUT}]) 29638 0.000038 send(18, "PASV\r\n", 6, 0) = 6 29638 0.000078 poll([{fd=18, events=POLLIN|POLLERR|POLLHUP}], 1, 240000) = 1 ([{fd=18, revents=POLLIN}]) 29638 0.000119 recv(18, "227 Entering Passive Mode (127,0"..., 4096, 0) = 45 29638 0.000048 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 20 29638 0.000029 fcntl64(20, F_GETFL) = 0x2 (flags O_RDWR) 29638 0.000025 fcntl64(20, F_SETFL, O_RDWR|O_NONBLOCK) = 0 29638 0.000026 connect(20, {sa_family=AF_INET, sin_port=htons(8721), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) 29638 0.000060 poll([{fd=20, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, 240000) = 1 ([{fd=20, revents=POLLOUT}]) 29638 0.000039 getsockopt(20, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 29638 0.000028 fcntl64(20, F_SETFL, O_RDWR) = 0 29638 0.000024 poll([{fd=18, events=POLLOUT}], 1, 240000) = 1 ([{fd=18, revents=POLLOUT}]) 29638 0.000036 send(18, "NLST /.maintenance\r\n", 20, 0) = 20 29638 0.000053 poll([{fd=18, events=POLLIN|POLLERR|POLLHUP}], 1, 240000) = 1 ([{fd=18, revents=POLLIN}]) 29638 0.000187 recv(18, "150 Here comes the directory lis"..., 4096, 0) = 39 29638 0.000111 poll([{fd=20, events=POLLIN|POLLERR|POLLHUP}], 1, 240000) = 1 ([{fd=20, revents=POLLIN}]) 29638 0.000037 recv(20, "", 4096, 0) = 0 29638 0.000024 close(20) = 0 29638 0.000038 lseek(19, 0, SEEK_SET) = 0 29638 0.000026 read(19, "", 8192) = 0 29638 0.000031 close(19) = 0 29638 0.000023 unlink("/tmp/php9Ldioo") = 0 29638 0.000042 poll([{fd=18, events=POLLIN|POLLERR|POLLHUP}], 1, 240000) = 1 ([{fd=18, revents=POLLIN}]) 29638 0.000037 recv(18, "226 Directory send OK.\r\n", 4096, 0) = 24 29638 0.000063 poll([{fd=18, events=POLLOUT}], 1, 240000) = 1 ([{fd=18, revents=POLLOUT}]) 29638 0.000038 send(18, "CWD /.maintenance/\r\n", 20, 0) = 20 29638 0.000035 poll([{fd=18, events=POLLIN|POLLERR|POLLHUP}], 1, 240000) = 1 ([{fd=18, revents=POLLIN}]) 29638 0.000067 recv(18, "550 Failed to change directory.\r"..., 4096, 0) = 33 29638 0.000050 poll([{fd=18, events=POLLOUT}], 1, 240000) = 1 ([{fd=18, revents=POLLOUT}]) 29638 0.000037 send(18, "PWD\r\n", 5, 0) = 5 29638 0.000052 poll([{fd=18, events=POLLIN|POLLERR|POLLHUP}], 1, 240000) = 1 ([{fd=18, revents=POLLIN}]) 29638 0.000035 recv(18, "257 \"/\"\r\n", 4096, 0) = 9 29638 0.000047 poll([{fd=18, events=POLLOUT}], 1, 240000) = 1 ([{fd=18, revents=POLLOUT}]) 29638 0.000036 send(18, "RMD /.maintenance\r\n", 19, 0) = 19 29638 0.000059 poll([{fd=18, events=POLLIN|POLLERR|POLLHUP}], 1, 240000) = 1 ([{fd=18, revents=POLLIN}]) 29638 0.000035 recv(18, "550 Remove directory operation f"..., 4096, 0) = 40 29638 0.002773 brk(0x929f000) = 0x929f000 29638 0.001533 brk(0x92df000) = 0x92df000 29638 0.001396 brk(0x931f000) = 0x931f000 29638 0.001436 brk(0x935f000) = 0x935f000 29638 0.001488 brk(0x939f000) = 0x939f000 29638 0.001460 brk(0x93df000) = 0x93df000 29638 0.001388 brk(0x941f000) = 0x941f000 29638 0.001452 brk(0x945f000) = 0x945f000 29638 0.000772 brk(0x949f000) = 0x949f000 29638 0.000668 brk(0x94df000) = 0x94df000 29638 0.001326 brk(0x951f000) = 0x951f000 29638 0.001320 brk(0x955f000) = 0x955f000 29638 0.001423 brk(0x959f000) = 0x959f000 29638 0.001508 brk(0x95df000) = 0x95df000 29638 0.001410 brk(0x961f000) = 0x961f000 29638 0.000280 brk(0x965f000) = 0x965f000 /29638 0.001073 brk(0x969f000) = 0x969f000 29638 0.001342 brk(0x96df000) = 0x96df000 29638 0.001341 brk(0x971f000) = 0x971f000 29638 0.001389 brk(0x975f000) = 0x975f000 29638 0.001385 brk(0x979f000) = 0x979f000 29638 0.001172 brk(0x97df000) = 0x97df000

它看起來像一個無限循環,因為 wp-admin/includes/file.php 的第 159 行是對函式 wp_tmpnam() 的遞歸呼叫。它破壞了更新過程,因此可能值得檢查這個小的更正,它描述了您的問題:wordpress bug fix

記憶體洩漏(或只是高記憶體使用)幾乎總是因為 Wordpress。

Wordpress 是眾所周知的記憶體和 CPU 佔用者,尤其是在您使用不良外掛和模板的情況下。

您可以嘗試一個一個地禁用所有外掛和模板,直到找到導致高記憶體使用的一個並用另一個類似的替換它或將問題報告給它的作者為您修復它。

如果您不是 WP 開發人員並且不了解 PHP,那麼您無法解決導致高記憶體使用的實際問題。

在某些情況下,某些 PHP 模組會導致類似的行為或只是段錯誤。如果禁用 WP 上的所有內容並沒有改變任何內容,您可以嘗試一個一個禁用 PHP 的模組,看看是否有任何變化。

尤其是與記憶體有關的模組(例如 Xcache、APC、eAccelerator 等)

如果您確實了解 PHP 並且想更深入一點,您還可以為 PHP 安裝xhprof模組,以便能夠在 wordpress 執行時進行分析,以查看哪些方法、函式等佔用了所有記憶體並從那裡開始。

引用自:https://serverfault.com/questions/703506