Исполняемый PHP-файл: настройка, запуск и администрирование

Раздел: Администрирование веб-сервера -> Управление процессами

Исполняемый файл PHP: настройка и запуск скриптов в режиме командной строки

Основное решение: использование shebang и прав на выполнение

Для запуска PHP-скрипта как самостоятельного исполняемого файла в среде Linux/Unix достаточно добавить в первую строку скрипта шебанг (shebang) с указанием пути к интерпретатору PHP и выставить бит выполнения. После этого файл можно запускать напрямую: ./script.php.


#!/usr/bin/php
<?php
echo "Hello, World!\n";
?>
  

выполнение файлов php (выполнение файлов php)

Шаги настройки:

  1. Создать файл, например hello.php, с содержимым выше.
  2. Установить права: chmod +x hello.php.
  3. Запустить: ./hello.php.

Этот метод применим для любых скриптов, которые должны выполняться из командной строки (CLI), для задач cron, фоновых процессов и т.д.

Как выполнить PHP-скрипт без shebang и прав?

Если по каким-то причинам нельзя изменять файл, можно использовать команду php -f:

php -f script.php

исполняемый php файл (исполняемый файл php)

Этот способ не требует настройки исполняемости, но требует указания интерпретатора каждый раз.

Типичная ошибка: команда не найдена (php: not found).

Решение: проверить установку PHP CLI (php -v) и полный путь в shebang (например, #!/usr/bin/env php для переносимости).

Как передать аргументы командной строки в исполняемый PHP-скрипт?

После shebang скрипт может принимать аргументы как обычная программа. Используйте массив $argv или функцию getopt():


#!/usr/bin/php
<?php
print_r($argv);
?>
  

Запуск: ./script.php --name=John -v выведет все аргументы.

Проблема: некорректное распознавание опций.

Решение: использовать getopt() с правильными спецификациями или библиотеку Symfony Console.

Как создать долго работающий процесс (демон) на PHP?

Для фоновых задач используется pcntl_fork() и управление сигналами. Пример минимального демона:


#!/usr/bin/php
<?php
// Отключение буферизации вывода
ob_implicit_flush(true);

$pid = pcntl_fork();
if ($pid == -1) {
    die('fork failed');
} elseif ($pid) {
    // Родительский процесс завершается
    exit(0);
}

// Дочерний процесс становится лидером сессии
posix_setsid();

// Основной цикл
while (true) {
    // Логика демона
    sleep(10);
}
?>
  

Важно: демоны обычно требуют обработки сигналов (SIGTERM, SIGHUP) для корректного завершения.

Ошибка: zомби-процессы при отсутствии обработки SIGCHLD.

Решение: использовать pcntl_signal() или вызывать pcntl_wait() в родителе.

Как управлять процессами через Supervisor (система мониторинга)?

Supervisor запускает и перезапускает PHP-демоны. Пример конфигурации для файла /etc/supervisor/conf.d/myapp.conf:


[program:myapp]
command=/usr/bin/php /home/user/daemon.php
autostart=true
autorestart=true
user=www-data
stderr_logfile=/var/log/myapp.err.log
stdout_logfile=/var/log/myapp.out.log
  

После обновления конфигурации: supervisorctl reread && supervisorctl update.

Проблема: PHP-скрипт не видит переменные окружения.

Решение: добавить опцию environment в конфигурацию Supervisor.

Как запускать PHP-скрипт по расписанию (cron)?

Добавить в crontab строку с запуском исполняемого скрипта или через php:


# Запуск каждый час
0 * * * * /usr/bin/php /path/to/script.php
# Или если скрипт исполняемый:
0 * * * * /path/to/script.php
  

Обратите внимание на полные пути, так как cron имеет ограниченное окружение.

Ошибка: скрипт не выполняется или вывод не записывается.

Решение: перенаправить вывод в файл для отладки: /path/to/script.php >> /var/log/script.log 2>&1.

Расширенные примеры исполняемых PHP-файлов

Пример 1: Интерактивный скрипт с обработкой аргументов

Пример

#!/usr/bin/env php
<?php
$longopts = [
    'input:',  // обязательное значение
    'verbose', // флаг
    'output::' // необязательное значение
];
$options = getopt('i:vo::', $longopts);
print_r($options);
?>
  
$ ./script.php -i input.txt -v --output=result.log
Array
(
    [i] => input.txt
    [v] => 
    [output] => result.log
)
  

Пояснение: флаги можно комбинировать, а для длинных опций используется двойное тире.

Пример 2: Демон с обработкой сигналов

Пример

#!/usr/bin/php
<?php
$stop = false;

pcntl_signal(SIGTERM, function ($signo) use (&$stop) {
    $stop = true;
});

pcntl_signal(SIGHUP, function ($signo) {
    // Перезагрузка конфигурации
});

$pid = pcntl_fork();
if ($pid == -1) exit(1);
if ($pid) exit(0); // родитель завершается

posix_setsid();

while (!$stop) {
    pcntl_signal_dispatch();
    // работа демона
    sleep(5);
}

echo "Демон завершился по сигналу\n";
?>
  

Запуск в фоне: ./daemon.php &. Для остановки: kill $(pgrep -f daemon.php).

(нет вывода, процесс в фоне)
  

Пример 3: Параллельное выполнение через proc_open

Пример

#!/usr/bin/php
<?php
$descriptorspec = [
    0 => ['pipe', 'r'],
    1 => ['pipe', 'w'],
    2 => ['pipe', 'w']
];

$processes = [];
for ($i = 0; $i < 3; $i++) {
    $cmd = sprintf('/usr/bin/php -r "sleep(2); echo \"Job %d\\n\";"', $i);
    $processes[$i] = proc_open($cmd, $descriptorspec, $pipes);
    if (is_resource($processes[$i])) {
        fclose($pipes[0]); // закрываем stdin
        echo stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        fclose($pipes[2]);
        proc_close($processes[$i]);
    }
}
?>
  
Job 0
Job 1
Job 2
  

Обратите внимание: данный пример последовательный. Для истинного параллелизма нужно запускать процессы и собирать вывод асинхронно.

Пример 4: Использование расширения pcntl для fork-сервера

Пример

#!/usr/bin/php
<?php
$max_children = 5;
$children = [];

while (true) {
    // Очистка завершённых дочерних процессов
    foreach ($children as $i => $pid) {
        $status = null;
        $res = pcntl_waitpid($pid, $status, WNOHANG);
        if ($res === $pid) {
            unset($children[$i]);
        }
    }

    if (count($children) < $max_children) {
        $pid = pcntl_fork();
        if ($pid == -1) {
            die("fork error");
        } elseif ($pid === 0) {
            // дочерний процесс выполняет полезную работу
            sleep(rand(1,5));
            exit(0);
        } else {
            $children[] = $pid;
        }
    }
    sleep(1);
}
?>
  

Этот сервер обрабатывает до 5 одновременных задач.

Пример 5: Запуск PHP-скрипта в контейнере Docker как исполняемого

Пример

FROM php:8.2-cli
COPY script.php /usr/local/bin/myapp
RUN chmod +x /usr/local/bin/myapp
CMD ["myapp"]
  

Сборка: docker build -t myapp .. Запуск: docker run myapp. Скрипт исполняется как команда.

Исполняемый файл PHP - comments

En
исполняемый php файл (php)