Блог - Linux, программирование, Я!

linux на сервере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 и наслаждаемся еще больше.

  1. enottrue
    2009-11-13 16:39:19 | #

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

  2. 2009-11-15 16:44:08 | #

    enottrue: и правда ведь)) Спасибо, поправил

  3. 2009-11-30 17:41:00 | #

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

  4. 2009-11-30 19:18:33 | #

    Да, согласен.
    Просто у меня порт 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
    
  5. TeXHaPb
    2010-03-31 18:53:29 | #

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