Побеждаем ошибки mod_fcgid/php-cgi ака suexec HTTP 500 и иже с ними, mod_fcgid: error reading data from FastCGI server

 Самыми распространенными ошибками mod_fcgid являются «Premature end of script headers», «can’t lock process table in pid», «can’t apply process slot», «couldn’t bind unix domain socket», «exit(communication error), get unexpected signal 11″…

Причины этих ошибок могут быть разные, от неправильных прав на файлы до неполной загрузки файла на сервер, не правильно написанного скрипта и неправильного режима передачи файла ASCII/Двоичный. Иногда бывает проблема кроется в переводе строк Windows формата, в этом случае может помочь команда col -bx <input_file> output_file (скобки обязательны!) или редактор notepad++ «Конверсия конца строки«.

Но когда mod_fcgid в целом работает нормально, а «Connection reset by peer: mod_fcgid: error reading data from FastCGI server, referer: …» и «Premature end of script headers: php-fcgi-wrapper, referer: …» продолжают регулярно появляться в error_log, при этом php_errors.log и /var/log/httpd/suexec.log не предоставляет никакой дополнительной информации, то копать нужно глубже — /var/log/messages или /var/log/kernel.log.

Chapter 1. Connection reset by peer: mod_fcgid: error reading data from FastCGI server

[Fri Dec 16 04:30:14.424452 2016] [fcgid:warn] [pid 26593] (104)Connection reset by peer: [client 127.0.0.1:42657] mod_fcgid: error reading data from FastCGI server, referer: http://example.com/install/index.php?restart=true
[Fri Dec 16 04:30:14.424564 2016] [core:error] [pid 26593] [client 127.0.0.1:42657] End of script output before headers: index.php, referer: http://example.com/install/index.php?restart=true

Если увеличение значений в FcgidProcessLifeTime, FcgidIOTimeout, FcgidIdleTimeout, FcgidBusyTimeout, не решает проблему, тогда нужно смотреть, а не используются ли PHP акселераторы типа APC. Например при использовании opcache в PHP 7 установка PrestaShop 1.7 обламывалась с ошибкой «Connection reset by peer: mod_fcgid: error reading data from FastCGI server«, в php.ini была указана директория для дополнительного кеширования байткода «opcache.file_cache=/var/www/.tmp«, но после того, как «;opcache.file_cache=/var/www/.tmp» была закомментирована — проблема исчезла.

Chapter 2. Premature end of script headers: php-fcgi-wrapper

Section 1. Причина №1 — неправильные «чмоды»

Основной причиной, как правило, появления этой ошибки может быть нехватка прав/полномочий на выполнение FastCGI скрипта, РНР в нашем случае.

Права на домашний каталог юзера в котором лежат файлы сайта должны быть 0755 и не меньше, а иначе будет «форбайден» (НТТР 403: 13PermissionDenied — Httpd Wiki), на файл же выполняющий обработку (онже FcgidWrapper) CGI скриптов «чмоды» (chmod) как минимум 750.

Если не помогло, смотрим иные варианты…

Section 2. Причина №2 — нахватка системных ресурсов

Например, первые ошибки mod_fcgid мы получили в error_log «Fri Mar 08 13:42:10 2013«:

[Fri Mar 08 13:42:10 2013] [warn] [client 81.83.хх.ххх] (104)Connection reset by 
peer: mod_fcgid: error reading data from FastCGI server, referer: ...
[Fri Mar 08 13:42:10 2013] [error] [client 81.83.хх.ххх] Premature end of script 
headers: php-fcgi-wrapper, referer: ...

Тогда открываем /var/log/messages или /var/log/kernel, находим системные события происходившие в упомянутое выше время вплоть до секунды и смотрим что же там творилось до и после ошибки php-cgi: http://pastebin.com/Gz5ccSNV

Как видим OOM Killer (oom-killer) начал прибивать процессы уже когда памяти совсем не осталось. OOM Killer — это реализация «Out of memory Killer» на уровне ядра Linux.

Виртуальной памяти (swap) в системе может быть немеряно, разумеется в пределах адресации HDD, а вот оперативной (RAM-ы) вполне ограниченное её количество. Бывают ситуации когда «чилды» (форки) процессов системы поедают ее всю (swap + RAM), и тут OOM Killer начинает среди процессов, кроме kernel init и threads, такой, который по его (oom-killer) мнению является самым ущербным (badness) и начинает его убивать.

В примере выше как раз возникла именно такая ситуация, когда «Free swap = 0kB» процессами (их чилдами/форками httpd-олигархов) httpd и php-cgi съедена вся память включая файл подкачки, «Swap is 100% used» и «Memory is 99% used» — обычно в таких ситуациях система уходит в нирвану и прекращает отвечать/реагировать на внешние команды.

Для решения проблемы поедания памяти рекомендуется снизить число чилдов (CHILDREN) апача и PHP, если PHP_FCGI_CHILDREN больше 2. Понизить значение PHP_FCGI_CHILDREN, а в случае использования PHP акселераторов типа APC и т.д. установить PHP_FCGI_CHILDREN = 0 ибо как сказано в секции «Special PHP considerations» официального мана mod_fcgid, чтоPHP акселератор APC не в состоянии расшаривать свой кэш для PHP модуля mod_fcgid если mod_fcgid/PHP использует управление процессами! Про иные акселераторы ничего не сказано, но всё же если используются любые акселераторы, то лучше управление процессами оставить на совести httpd демона.

Второй способ побороть ошибки «Connection reset by peer: mod_fcgid: error reading data from FastCGI server» и «Premature end of script headers: php-fcgi-wrapper» — это не устанавливать слишком высокое значение в PHP_FCGI_MAX_REQUESTS, которое по умолчанию равно = 500. Вместе с этим использовать директиву FcgidMaxRequestsPerProcess, значение которой должно быть <= PHP_FCGI_MAX_REQUESTS — т.е. если PHP_FCGI_MAX_REQUESTS = 1000, то и значение FcgidMaxRequestsPerProcess должно быть = 1000 или меньше, по умолчанию количество запросов отправляемых в php-cgi не контролируется, т.е. FcgidMaxRequestsPerProcess = 0.

В некоторых случаях помогает увеличение РНР лимита в php.ini, в директивах «max_execution_time = 180«, «max_input_time = 120» и «default_socket_timeout = 180«, а также установкой «FcgidIOTimeout 300» и «FcgidBusyTimeout 500» в vi /etc/httpd/conf/httpd.conf или же конфиге виртуального хоста — разумеется под каждые конкретные условия значения подбираются экспериментальным путём.

Следующим шагом будет выбор стратегии выделения памяти (OVERCOMMIT_GUESS (0), OVERCOMMIT_ALWAYS (1), OVERCOMMIT_NEVER (2)) отличной от стратегии по умолчанию. По умолчанию sysctl -w vm.overcommit_memory=0 система пытается оценить объем свободной памяти, а на практике же удовлетворяет все запросы к памяти до момента её полной утечки, после чего вызывает упомянутый выше OOM Killer (oom-killer) уже тогда, когда система ушла в нирвану «Free swap = 0kB», «Swap is 100% used» и «Memory is 99% used».

vm.overcommit_memory=1 почти тоже что и = 0, только теперь уже система не пытается оценивать объем свободной памяти, а делает вид, что её всегда хватает до момента её полной утечки. vm.overcommit_memory=2 запретит выделять больше памяти чем имеется в файле подкачки и больше оперативной памяти в процентном соотношении указанном в параметре vm.overcommit_ratio=?. Также можно вырубить эвристический поиск ущербного процесса для убивания, по умолчанию vm.oom_kill_allocating_task=0 (OOM Killer) сканирует весь список задач и на основе своего эвристического алгоритма выбирает процесс для убивания, что отнимает дополнительные ресурсы системы. Значение выше 0 запрещает сканировать список задач и говорит «OOM Killer-у» уничтожать любой процесс запросивший больше РАМ-ы чем имеется в наличии.

sysctl -w vm.overcommit_memory=2
sysctl -w vm.overcommit_ratio=90
sysctl -w vm.oom_kill_allocating_task=1

 

Для изменений на постоянной основе добавим в /etc/sysctl.conf. Ещё как вариант можно сделать ещё один файл подкачки, на случай вонючий:)

dd if=/dev/zero of=/root/swap1 bs=1024 count=1024K
1048576+0 records in
1048576+0 records out
1073741824 bytes (1.1 GB) copied, 8.61173 s, 125 MB/s
 
mkswap /root/swap1
Setting up swapspace version 1, size = 1048572 KiB
no label, UUID=ba18ffde-b25b-4844-9da4-6fd095c9182f
 
swapon /root/swap1
 
vi /etc/fstab
/root/swap1 swap swap defaults 0 0

 

Chapter 3. mod_fcgid: can’t lock process table in pid

Это сообщение «mod_fcgid: can’t lock process table in pid» (mod_fcgid: не может заблокировать таблицу процессов в pid) может возникать тогда, когда регулярно используется команда «apachectl graceful» — т.е. перезапуск без разрыва текущих соединений, а её выполнение попадает во время интенсивного использования/нагрузки сервера.

Chapter 4. mod_fcgid: can’t apply process slot

«mod_fcgid: can’t apply process slot» — mod_fcgid не может выделить слот для процесса…

Section 1. Причина №1 — проблемы сегментации

В лог файл виртуального хоста получили «[warn] [client 78.159.53.233] mod_fcgid: can’t apply process slot for /var/www/user/php/php-cgi-wrapper, referer: https://www.google.com.ua/«, а в лог файл самого сервера множественные «[crit] (22)Invalid argument: ap_queue_pop failed«.

Ошибкой «Invalid argument: ap_queue_pop failed» в лог файл /var/log/httpd/error_log нагадило мегов на 300 с лишним за какие-то считанные минуты. Этой ошибке предшествовали сообщения «[alert] (11)Resource temporarily unavailable: apr_thread_create: unable to create worker thread» и «[notice] child pid 2839 exit signal Segmentation fault (11) Error in my_thread_global_end(): 1 threads didn’t exit«.

На ibm.com рекомендовалось увеличить значение «sysctl -w kernel.threads-max=120000» (по умолчанию 3525 в CentOS 6 и 7877 в CentOS 5) и уменьшить «stack size» с 10240 кб до «ulimit -s 256«.

Размер для каждого потока «thread» равен размеру «stack size», а если Apache запущен как Workerи завышены значения MaxClients, MinSpareThreads, MaxSpareThreads и ThreadsPerChild, в условиях нехватки памяти, то получим «[alert] (11)Resource temporarily unavailable: apr_thread_create: unable to create worker thread Error in my_thread_global_end(): 1 threads didn’t exit»

Можно увеличить kernel.threads-max, но «stack size» лучше оставить как есть, а иначе на некоторых страницах сайта это может вызывать ошибку «exit(communication error), get unexpected signal 11«! Однако принимая во внимание предыдущий абзац, «stack size» можно попробовать урезать в 3-5 раза или же урезать ThreadsPerChild если продолжаем получать «Resource temporarily unavailable: apr_thread_create: unable to create worker thread«.

Установить ограничение для «stack size» на постоянной основе можно в конф. файле /etc/security/limits.conf:

....
 
*               soft    stack            2048
apache               hard    stack            5120
 
# End of file

В примере выше мягкий лимит на «stack size» для всех установлен в 2 МБ, а для пользователя apache ограничен жестким лимитом в 5 МБ. После изменения лимитов с помощью «ulimit -s 256» нужно остановить и снова запустить сервер «service httpd stop && service httpd start«, чтобы изменения вступили в силу, изменения в /etc/security/limits.conf вступят в силу после перезагрузки ОС!

Section 2. Причина №2 — проблема конфигурации

…»mod_fcgid: can’t apply process slot» может быть связана не только с ошибками сегментации, но и с другими причинами такими, как например конфигурация самого mod_fcgid. Рядом с ошибкой «mod_fcgid: can’t apply process slot» граничит и «apache https 503» (ака «Service Unavailable»).

Основную погоду делают параметры:

  • FcgidMaxProcesses — максимально допустимое число php-cgi процессов запущенных одновременно;
  • FcgidMaxProcessesPerClass — максимально допустимое число php-cgi процессов для каждого класса.

PerClass-ом в Апаче, имхо … как я понимаю, считается базовый хост и все его виртуальные хосты. Значит, если FcgidMaxProcessesPerClass 2, а виртуальных хостов у нас 15 + 1 базовый хост, то в итоге получаем 32 php-cgi процесса, но если FcgidMaxProcesses (1000 по умолчанию) будет ниже 32, то в итоге в лог можем получить «mod_fcgid: can’t apply process slot», а в браузер «503 Service Unavailable».

В некоторых случаях (зависит от нагрузки) значение FcgidMaxProcessesPerClass должно быть не меньше 3-5.

Chapter 5. exit(communication error), get unexpected signal 11

Эта ошибка результат уменьшения «stack size»:

less /var/log/httpd/error_log
 
[Sun Nov 03 00:40:30 2013] [error] mod_fcgid: process /var/www/wrs/php/php-cgi-w
rapper(2558) exit(communication error), get unexpected signal 11
 
[Sun Nov 03 00:40:30 2013] [warn] [client xxx.xxx.xxx.xxx] (104)Connection reset by
 peer: mod_fcgid: error reading data from FastCGI server, referer: http://example.
 com
[Sun Nov 03 00:40:30 2013] [error] [client xxx.xxx.xxx.xxx] Premature end of script
 headers: index.php, referer: http://example.com/
 
 
less /var/log/messages
 
Nov  3 00:56:21 samp kernel: php-cgi[2666]: segfault at 7fffe9034f30 ip
00000000004740c3 sp 00007fffe9034ef0 error 6 in php-cgi[400000+341000]

Premature end of script headers / exit(communication error), get unexpected signal 11 в некоторых случаях может возникать из-за PHP акселераторов типа APC, обычно отсутствует если PHP работает «Как модуль APACHE».

Примечательно, что данная ошибка может проявляться только на некоторых страницах, обычно больших по размеру, где, например, может быть много кода раскрашиваемого Geshi плагином. Часто такие страницы создают большую нагрузку на ЦП и превысив всевозможные лимиты вызывают segfault.

Chapter 6. user mismatch (daemon instead of www)

Связанные ошибки:

/home/user/logs/error_log
[Mon Dec 16 12:36:19.011343 2013] [fcgid:warn] [pid 17033:tid 2183892224] [clien
t 178.94.242.15:54550] mod_fcgid: error reading data, FastCGI server closed conn
ection
[Mon Dec 16 12:36:19.016230 2013] [core:error] [pid 17033:tid 2183892224] [clien
t 178.94.242.15:54550] End of script output before headers: writetest.php
 
---
 
logs/error_log
suexec policy violation: see suexec log for more details
 
---
 
logs/suexec_log
[2013-12-16 12:36:19]: user mismatch (daemon instead of www)

Ошибка вызвана несовпадением имени пользователя указанного в директиве AP_HTTPD_USER, имя которого можно узнать выполнив «suexec -V«, с именем пользователя, которое указано в /var/www/conf/httpd.conf.

В данном случае AP_HTTPD_USER для suexec = www, а имя указанное в httpd.conf = daemon. Решение: в конфиге /var/www/conf/httpd.conf, в директивах User и Group указать имя www вместо daemon.

Chapter 7. mod_fcgid: couldn’t bind unix domain socket /var/www/logs/fcgidsock/29944.19

Сопутствующие ошибки:

[Mon Dec 16 12:40:29.310746 2013] [fcgid:warn] [pid 29944:tid 665836768] (13)Per
mission denied: mod_fcgid: spawn process /home/user/php/php-cgi-wrapper error
[Mon Dec 16 12:40:30.344063 2013] [fcgid:error] [pid 29944:tid 665836768] (13)Pe
rmission denied: mod_fcgid: couldn't bind unix domain socket /var/www/logs/fcgid
sock/29944.19

Решается сменой прав на каталог «chmod 777 /var/www/logs/fcgidsock/» или же сменой каталога директивой FcgidIPCDir

Если есть ещё какие вопросы по другим ошибкам mod_fcgid, то пишем в комментарии…

Chapter 8. Ссыль по теме:

Автор: Олег Головский

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.