Выбор порта для PHP сервера: практическое руководство

Раздел: Администрирование PHP сервера -> Конфигурация сервера

Настройка порта PHP сервера: варианты и инструкции

Номер порта определяет, на каком сетевом интерфейсе сервер ожидает соединения. Для PHP существуют два основных сценария: встроенный веб-сервер для разработки (php -S) и сервер приложений PHP-FPM для продакшена. Рассмотрим оба подхода.

Встроенный PHP сервер с указанием порта

Наиболее простой и эффективный способ запустить PHP сервер на заданном порту - использовать встроенный сервер из командной строки. Команда php -S localhost:8080 запустит сервер на порту 8080, доступный только с локального компьютера. Если требуется доступ с других устройств, привязка делается к адресу 0.0.0.0:

php -S 0.0.0.0:8000

После запуска в консоли появится сообщение Listening on http://0.0.0.0:8000. Сервер будет обрабатывать запросы до нажатия Ctrl+C.

Типичная ошибка: порт уже занят

Если порт занят другим процессом, появится сообщение Address already in use. Решение: сменить порт (например, php -S localhost:8081) или завершить процесс, занимающий порт. Для поиска процесса используется команда:

lsof -i :8080

Найти PID и выполнить kill -9 PID.

Вариант 1: Изменение порта в PHP-FPM

Как изменить порт для PHP-FPM, если стандартный 9000 занят?

В конфигурации пула (обычно файл /etc/php/8.1/fpm/pool.d/www.conf) параметр listen задаёт адрес и порт. Например, для перехода на порт 9001:

listen = 127.0.0.1:9001

После изменения требуется перезапустить службу:

sudo systemctl restart php8.1-fpm

Проверить успешность можно командой netstat -tlnp | grep php - должен появиться порт 9001.

Проблема: SELinux блокирует порт

Если используется SELinux, нестандартный порт может быть запрещён. Решение - разрешить порт в контексте httpd_port_t:

sudo semanage port -a -t httpd_port_t -p tcp 9001

Вариант 2: Использование unix-сокета вместо TCP порта

Как перевести PHP-FPM на unix-сокет для повышения производительности?

Unix-сокеты быстрее TCP и не занимают порт. Настройка в том же файле пула:

listen = /run/php/php8.1-fpm.sock

Перезапуск службы. Веб-сервер (например, nginx) должен использовать сокет вместо адреса:

fastcgi_pass unix:/run/php/php8.1-fpm.sock;

Ошибка: permission denied

Права на сокет должны соответствовать пользователю веб-сервера. В конфигурации FPM добавляют строки listen.owner = www-data и listen.group = www-data.

Вариант 3: Множественные порты для разных приложений

Как запустить два PHP приложения на разных портах через один экземпляр FPM?

Создаются отдельные конфигурационные файлы пулов в /etc/php/*/fpm/pool.d/. Например, site1.conf с портом 9002 и site2.conf с портом 9003. Каждый пул может иметь свои настройки (путь к скриптам, пользователь).

; site1.conf
[site1]
listen = 127.0.0.1:9002
user = site1user
pm = dynamic

; site2.conf
[site2]
listen = 127.0.0.1:9003
user = site2user
pm = dynamic

Перезапуск FPM, затем nginx направляет запросы на соответствующий порт:

# в конфигурации virtual host
location ~ \.php$ {
  fastcgi_pass 127.0.0.1:9002;
}

Проблема: пулы не стартуют из-за одинаковых имён сокетов

Каждый пул должен иметь уникальный идентификатор (имя в квадратных скобках) и уникальный listen.

Вариант 4: Привязка встроенного сервера к определённому интерфейсу

Как сделать PHP сервер доступным только с определённого IP?

Вместо localhost или 0.0.0.0 указывается конкретный IP-адрес. Например, чтобы сервер слушал только на интерфейсе 192.168.1.100:

php -S 192.168.1.100:8080

Это полезно для изоляции доступа в многосетевой среде. Если сервер привязан к неверному адресу, соединения не будут приниматься.

Расширенные примеры настройки порта PHP сервера

Пример 1: Встроенный сервер с файлом-роутером

Можно запустить сервер с PHP-скриптом, который обрабатывает все запросы (роутер). Пример router.php:

Пример
// router.php
$uri = $_SERVER['REQUEST_URI'];
if ($uri === '/api') {
    http_response_code(200);
    echo 'API endpoint';
} else {
    return false; // передать обработку статическим файлам
}

Запуск:

Пример
php -S localhost:8000 router.php

Результат: при обращении к http://localhost:8000/api сервер вернёт API endpoint, а для остальных путей будет искать файл в текущей директории.

$ curl http://localhost:8000/api
API endpoint

Пример 2: Динамический выбор свободного порта с помощью скрипта

Бывает необходимо запустить сервер на случайном свободном порту. Скрипт findport.php находит порт и запускает сервер:

Пример
// findport.php
$basePort = 8000;
$maxAttempts = 10;
for ($port = $basePort; $port < $basePort + $maxAttempts; $port++) {
    $socket = @fsockopen('127.0.0.1', $port, $errno, $errstr, 1);
    if (!$socket) {
        echo "Starting server on port $port\n";
        exec("php -S localhost:$port");
        break;
    }
    fclose($socket);
}

Запуск: php findport.php. Результат - сервер стартует на первом свободном порту, начиная с 8000.

Starting server on port 8000

Пример 3: Настройка PHP-FPM на нестандартный порт и проверка

Предположим, нужно изменить порт FPM на 9001. Файл /etc/php/8.2/fpm/pool.d/www.conf содержит строку:

Пример
listen = 127.0.0.1:9001

Перезапуск и проверка:

Пример
sudo systemctl restart php8.2-fpm
netstat -tlnp | grep php
tcp  0  0 127.0.0.1:9001  0.0.0.0:*  LISTEN  12345/php-fpm

Если порт не появился, проверяют логи FPM: tail -f /var/log/php8.2-fpm.log.

Пример 4: Использование unix-сокета в nginx

Конфигурация nginx при использовании unix-сокета вместо TCP порта:

Пример
server {
    listen 80;
    server_name example.com;
    root /var/www/example;

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

Перезагрузка nginx: sudo systemctl reload nginx. Ошибка соединения обычно проявляется кодом 502 Bad Gateway и записью в логе ошибок nginx.

Пример 5: Запуск встроенного сервера в фоне и его остановка

Чтобы сервер работал после закрытия терминала, используют запуск в фоне:

Пример
php -S 0.0.0.0:8080 > /dev/null 2>&1 &

Запомнить PID: echo $! сохраняют в переменной. Остановка по PID:

Пример
kill PID

Можно использовать pkill -f 'php -S' для остановки всех процессов.

Пример 6: Проверка занятости порта из PHP

Скрипт проверяет, свободен ли порт:

Пример
$port = 8080;
$connection = @fsockopen('127.0.0.1', $port, $errno, $errstr, 1);
if (is_resource($connection)) {
    echo "Порт $port занят.";
    fclose($connection);
} else {
    echo "Порт $port свободен.";
}
Порт 8080 свободен.

Порт PHP сервера - comments

En
Server port php (php)