Nginx + PHP-fcgi на Ubuntu

Если быть точным, опишу переход с режима работы Nginx <-> Apache backend на Nginx <-> php-fcgi backend.

Т.е. об отказе от промежуточного, в общем-то бесполезного слоя в виде апача между Nginx (http сервер) и PHP (application сервер)

Отдельно хочу заметить, что в этом руководстве мы обойдемся без компиляции чего-бы то ни было

Что имеем на данный момент:

Имеется домен с поддоменами, сервер на Ubuntu 9.10 с веб-сервером Nginx, который слушает 80 порт, и Апач с mod-php, висящий на localhost:8080 (в качестве прокси-бэкенда нгинкса). Для коннекта к апачу в /etc/nginx/sites-enabled лежит симлинк на файлик 100apache_proxy следующего содержания:

server {
listen       80;
server_name  seriyps.ru *.seriyps.ru localhost;
access_log  /var/log/nginx/apache_proxy.access.log;
location / {
	proxy_pass      http://localhost:8080;#проксируем данные на апач
	proxy_connect_timeout 15;#время ожидания ответа от апача - 15 секунд, можно больше
	proxy_redirect  off;
	proxy_set_header	Host    $host;#Ставим HTTP заголовок Host
	proxy_set_header	X-Real-IP $remote_addr;#Заголовок X_Real-Ip т.к. внешние запросы принимает NGINX а апачу достаются в качестве IP только 172.0.0.1
	proxy_set_header	X-Forwarded-For $proxy_add_x_forwarded_for;#то-же самое
}

В итоге хотим:

ПЛАВНО перейти с использования apache прослойки на полное использование nginx<->php-fcgi с минимальными простоями сервера.

Приступим!

Настройка PHP для работы в режиме fast-CGI

Для начала поставим пакет php5-cgi (он нужен для использования PHP отдельно от apache)

sudo apt-get install php5-cgi

Затем ставим пакетик spawn-fcgi Эта утилитка нужна для удобного управления fast-cgi процессами независимо от веб-сервера.

sudo apt-get install spawn-fcgi

После чего создаем скрипт для запуска php5-fcgi процесса через spawn-fcgi

#!/bin/sh
### BEGIN INIT INFO
# Provides:          php5-fcgi
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the php5-cgi in fast-cgi mode
# Description:       configure and starts php5-cgi processes in fast-cgi mode using spawn-fcgi
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin
SCRIPTNAME="/etc/init.d/php5-fcgi"

FCGI_PIDFILE="/var/run/spawn-php5-fcgi.pid"
## Абсолютный путь до spawn-fcgi
FCGI_DAEMON="/usr/bin/spawn-fcgi"

## php переключится на этого юзера и группу (делать такими-же, как у апача)
USER=www-data
GROUP=www-data
## Абсолютный путь до  php
FCGI_PROGRAM="/usr/bin/php5-cgi"
## Количество запущенных процессов PHP-fcgi, см http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:PerformanceFastCGI#How-many-PHP-processes-do-I-need
PHP_FCGI_CHILDREN=10
## максимальное количество запросов, которое обработает отдельный PHP - fcgi процесс до своего перезапуска
PHP_FCGI_MAX_REQUESTS=1000
## TCP порт, который будет слушать php-fcgi
FCGI_PORT="9000"
## IP адреса, по которым будет доступен PHP-fcgi (через запятую)
FCGI_IP="127.0.0.1"

test -x $FCGI_PROGRAM || exit 0
test -x $FCGI_DAEMON || exit 0

set -e

export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS

. /lib/lsb/init-functions

case "$1" in
  start)
        log_daemon_msg "Starting spawn-fcgi"
        if ! $FCGI_DAEMON -a $FCGI_IP -p $FCGI_PORT -f $FCGI_PROGRAM -u $USER -g $GROUP -C $PHP_FCGI_CHILDREN -P $FCGI_PIDFILE; then
            log_end_msg 1
        else
            log_end_msg 0
        fi
        RETVAL=$?
  ;;
  stop)
        log_daemon_msg "Killing all spawn-fcgi processes"
	start-stop-daemon --stop --pidfile $FCGI_PIDFILE --signal 2 & log_end_msg 0 || log_end_msg 1
        #if killall --signal 2 php5-cgi > /dev/null 2 > /dev/null; then
        #    log_end_msg 0
        #else
        #    log_end_msg 1
        #fi
        RETVAL=$?
  ;;
  restart|force-reload)
        $0 stop
        #sleep 1
        $0 start
  ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
        exit 1
  ;;
esac

exit $RETVAL

Этот скрипт – несколько адаптированная версия скрипта из примера в документации сервера lighttpd http://redmine.lighttpd.net/projects/lighttpd/wiki/ScriptsUbuntu приспособленная для работы с rc.d правилами Ubuntu/Debian. Можно сделать попроще – см http://redmine.lighttpd.net/projects/spawn-fcgi/wiki/Basic_Ideas но в таком случае за перезапуском PHP при загрузке придется следить самостоятельно

Сохраняем этот скрипт как /etc/init.d/php5-fcgi и даем права на исполнение:

sudo chmod +x /etc/init.d/php5-fcgi

Обновляем правила rc.d для автоматического запуска php5-fcgi при старте системы:

sudo update-rc.d php5-fcgi defaults

Запускаем:

sudo service php5-fcgi start

spawn-fcgi: child spawned successfully: PID: 23620

Проверяем:

ps xa | grep php5-cgi

Должен выдать что-то вроде

23620 ?        Ss     0:00 /usr/bin/php5-cgi
23622 ?        S      0:00 /usr/bin/php5-cgi
23623 ?        S      0:00 /usr/bin/php5-cgi
23624 ?        S      0:00 /usr/bin/php5-cgi
23625 ?        S      0:00 /usr/bin/php5-cgi
23626 ?        S      0:00 /usr/bin/php5-cgi
23627 ?        S      0:00 /usr/bin/php5-cgi
23628 ?        S      0:00 /usr/bin/php5-cgi
23629 ?        S      0:00 /usr/bin/php5-cgi
23630 ?        S      0:00 /usr/bin/php5-cgi
23631 ?        S      0:00 /usr/bin/php5-cgi

Если вы видите то-же самое, значит, скорее всего, все сделано правильно! Обратите внимание на процесс 23620 ? Ss 0:00 /usr/bin/php5-cgi – это что-то наподобие мастер-процесса, он является родителем для остальных процессов php5-cgi. Убиваем его – убиваем все процессы php5-cgi.
Первая часть настройки закончена!

Настройка Nginx для работы с php-fcgi

Тут все просто (если не нужно настраивать url-rewrite правила).
В папочке /etc/nginx/sites-available создаем файлик, например 20yourdomain.com примерно следующего содержания:

#/etc/nginx/sites-available/20yourdomain.com
server {
	listen   80;
	server_name  yourdomain.com;

	access_log  /var/log/nginx/yourdomain_com.log;
	root   /var/www/yourdomain.com;
	index  index.php index.html index.htm;

	# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9090
	#
	location ~ \.php$ {
		fastcgi_pass   127.0.0.1:9000;
		fastcgi_index  index.php;
		fastcgi_param  SCRIPT_FILENAME  /var/www/yourdomain.com$fastcgi_script_name;
		include fastcgi_params;
	}
	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	location ~ /\.ht {
		deny  all;
	}

}

(места, выделенные жирным шрифтом замените на ваши данные)

Создаем на него символическую ссылку в /etc/nginx/sites-enabled

sudo ln -s /etc/nginx/sites-available/<strong>20yourdomain.com </strong>/etc/nginx/sites-enabled/<strong>20yourdomain.com</strong>

Проверяем правильность конфига

sudo service nginx configtest

Testing nginx configuration: the configuration file /etc/nginx/nginx.conf syntax is ok
configuration file /etc/nginx/nginx.conf test is successful
nginx.

Готово! перезапускаем Nginx

sudo service nginx restart

и наслаждаемся! При необходимости проделываем эту процедуру для каждого поддомена, добавляем правила URL-rewrite и наслаждаемся еще больше.

7 thoughts on “Nginx + PHP-fcgi на Ubuntu

  1. enottrue

    прям в начале статьи sudo apt-get install spawn-fcgi 2 раза. install php5-cgi нет.
    а в остальном спасибо за труд)

    Reply
  2. vitok

    Первое (и последнее) на чем запоролся в этой статье это:
    FCGI_PORT=\9090\
    в нгинксе дефолтом 9000 порт стоит, может в статейке стоило б сменить в скрипте запуска порт?
    В чем магическая разница запуска php-cgi на 9000 и на 9090 порте?
    А за статью огромное спасибо, особенно скрипт запуска очень выличил!

    Reply
  3. P.S. Post author

    Да, согласен.
    Просто у меня порт 9000 был занят, и я не долго думая его и подменил на первое что пришло в голову.
    Поправил!

    Еще хочу заметить один момент – при использовании со скриптом команды

    sudo service php5-fcgi restart

    может выскочить ошибка в стиле “этот порт уже занят”.

    spawn-fcgi: bind failed: Address already in use

    Я вылечил костылем – вставил между остановкой и запуском

    restart|force-reload)
            $0 stop
            $0 start

    паузу примерно в одну секунду:

    restart|force-reload)
            $0 stop
            sleep 1
            $0 start
    Reply
  4. TeXHaPb

    Я нашел немного другой вариант. Исправление в начале файла – зависимости для старта:
    # Required-Start: $local_fs $remote_fs $network $syslog
    # Required-Stop: $local_fs $remote_fs $network $syslog

    Reply
    1. P.S. Post author

      О.. я, честно говоря, в эти тонкости не вникал) Это-же информация для Upstat, как я понимаю?
      Не подскажете где об этом почитать можно?

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *