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

Раздел: Работа с PHP из командной строки -> Настройка окружения PHP

Командная строка PHP (CLI) предоставляет широкие возможности для выполнения скриптов, автоматизации задач, тестирования и отладки без участия веб-сервера. В этой части статьи рассматриваются основные способы взаимодействия с PHP из терминала, включая запуск файлов, передачу параметров, работу с потоками ввода-вывода и использование встроенного сервера.

Основные возможности командной строки PHP

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

Самый распространённый способ запуска PHP-скрипта – указать интерпретатор php и путь к файлу. Если PHP установлен и добавлен в переменную окружения PATH, команда php script.php запустит файл script.php в текущей директории. PHP выполнит код и выведет результат в консоль.

php script.php

Php не является внутренней или внешней командой (php не является внутренней или внешней командой)

В скрипте можно использовать константы PHP_SAPI (значение 'cli') или функцию php_sapi_name(), чтобы убедиться, что выполнение происходит в режиме командной строки.

Типичная ошибка: Could not open input file: script.php. Это сообщение появляется, если файл не найден. Необходимо проверить путь и наличие файла. Также может возникнуть синтаксическая ошибка – PHP Parse error. Перед запуском рекомендуется проверять синтаксис командой php -l script.php.

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

Аргументы командной строки помещаются после имени файла. Внутри скрипта они доступны через суперглобальный массив $argv (первый элемент – имя скрипта) и переменную $argc (количество аргументов).

php script.php arg1 arg2 arg3

Php could not find driver (ошибка "could not find driver" в php)

Пример скрипта, выводящего переданные аргументы:

<?php
foreach ($argv as $index => $arg) {
    echo "Arg $index: $arg\n";
}
?>

Get env php (получение переменных окружения)

Arg 0: script.php
Arg 1: arg1
Arg 2: arg2
Arg 3: arg3

Usr share php (путь usr/share/php)

Возможные проблемы: если аргумент содержит пробелы, его следует заключать в кавычки, иначе оболочка разделит его на несколько аргументов. Например: php script.php "слово с пробелами". Также некоторые специальные символы (например, $) могут интерпретироваться оболочкой – их нужно экранировать.

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

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

php -r "echo 'Hello, World!';"

Php command line (командная строка php (cli))

Hello, World!

Можно использовать сложные конструкции, но важно корректно экранировать кавычки. Рекомендуется снаружи ставить одинарные кавычки, а внутри – двойные.

Распространённая ошибка: при использовании двойных кавычек снаружи оболочка может интерпретировать переменные. Например, php -r "echo $foo;" вызовет ошибку, если переменная оболочки не определена. Правильно: php -r 'echo "$foo";' или экранирование.

Как использовать интерактивный режим (REPL) PHP?

Режим -a (interactive) запускает оболочку PHP, где можно вводить код построчно. Каждое выражение тут же выполняется и выводит результат (если есть).

php -a
Interactive shell

php > echo 'test';
test
php > exit

В интерактивном режиме доступны автодополнение (Tab) и история команд. Это полезно для экспериментов и отладки отдельных выражений.

Ограничение: некоторые функции, требующие полной инициализации модулей, могут работать некорректно. Например, функции сессии могут выдавать предупреждения. Для выхода используется команда exit или quit.

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

Опция -S позволяет поднять легковесный веб-сервер, полезный для тестирования приложений без Apache или Nginx.

php -S localhost:8000

Сервер запускается в текущей директории, обслуживая статические файлы и PHP-скрипты. Можно указать корневой каталог и маршрутизатор (роутинг) через третий параметр.

php -S localhost:8000 -t /path/to/public
php -S localhost:8000 router.php

Предупреждение: встроенный сервер однопоточный и не предназначен для production. При каждом запросе он выполняет код последовательно, что может приводить к блокировкам. Также не поддерживается HTTPS.

Как проверить синтаксис PHP-файла?

Опция -l (lint) анализирует файл на наличие синтаксических ошибок без выполнения.

php -l script.php
No syntax errors detected in script.php

Если ошибка есть, будет указан номер строки и описание. Этот метод полезен в CI/CD или перед деплоем.

Примечание: проверка не выявляет логические ошибки или проблемы с производительностью. Для полного анализа используются статические анализаторы.

Как получить информацию о PHP и установленных модулях?

Команда php -i выводит расширенную конфигурацию, аналогичную функции phpinfo() в веб-версии. php -m показывает список загруженных модулей. php -v отображает версию.

php -i | grep memory_limit
php -m
php -v
memory_limit => 128M => 128M
[PHP Modules]
calendar, Core, ctype, ...
PHP 8.3.6 (cli) (built: Apr 11 2024 17:44:48) ( NTS )

Ошибка: если команда не найдена, значит PHP не установлен или не добавлен в PATH. Необходимо указать полный путь к исполняемому файлу.

Как использовать альтернативный php.ini для CLI?

Опция -c позволяет указать путь к конфигурационному файлу. Это удобно, когда нужно выполнить скрипт с особыми настройками, отличными от основного php.ini.

php -c /path/to/custom.ini script.php

Можно также временно изменить отдельные директивы с помощью -d.

php -d memory_limit=256M -d max_execution_time=60 script.php

Проблема: не все директивы допускают изменение во время выполнения через -d. Например, extension может быть только из ini-файла. Если указанный файл отсутствует, PHP использует стандартный.

Как читать данные из STDIN в PHP-скрипте?

PHP поддерживает поток php://stdin, который можно читать, например, с помощью file_get_contents() или fgets(). Это позволяет обрабатывать данные, переданные через конвейер (pipe).

php -r "echo strtoupper(file_get_contents('php://stdin'));"

Вызов в командной строке:

echo 'hello' | php -r "echo strtoupper(file_get_contents('php://stdin'));"
HELLO

Ошибка: если не перенаправлять STDIN, скрипт будет ожидать ввод с клавиатуры. Для завершения ввода используется Ctrl+D (Unix) или Ctrl+Z (Windows).

Как направлять ошибки в STDERR?

В CLI-режиме можно явно писать в поток STDERR с помощью fwrite(STDERR, 'сообщение'). Это позволяет отделить обычный вывод от сообщений об ошибках.

php -r 'fwrite(STDERR, "Ошибка\n"); echo "Нормальный вывод\n";'

В оболочке можно перенаправить STDERR в файл:

php script.php 2>error.log

Проблема: если забыть перенаправить STDERR, ошибки будут выводиться на экран вместе с обычным выводом, что может затруднить автоматическую обработку.

Как обрабатывать длинные и короткие опции командной строки (getopt)?

Функция getopt() разбирает аргументы, переданные скрипту, в соответствии с заданными опциями. Она поддерживает как короткие (-v), так и длинные (--verbose) опции.

<?php
$options = getopt('v::', ['verbose::']);
if (isset($options['v']) || isset($options['verbose'])) {
    echo 'Режим подробного вывода включён';
}
?>

Запуск: php script.php -v или php script.php --verbose.

Ошибка: если в опциях указаны несуществующие значения, getopt может вернуть некорректный результат. Следует запускать скрипт с опцией -- для отделения опций от аргументов.

Расширенные примеры использования PHP CLI

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

Скрипт может работать как долгоиграющий процесс, реагируя на сигналы от операционной системы. Для этого используются функции pcntl_signal() и pcntl_signal_dispatch().

Пример
<?php
declare(ticks = 1); // для старых версий PHP, в PHP 8 не требуется

pcntl_signal(SIGTERM, function ($signo) {
    echo "Получен сигнал $signo, завершаю работу.\n";
    exit(0);
});
pcntl_signal(SIGINT, function () {
    echo "Прерывание (Ctrl+C). Выход.\n";
    exit(0);
});

echo "Демон запущен. PID: " . getmypid() . "\n";
while (true) {
    echo "Работаю...\n";
    sleep(2);
    pcntl_signal_dispatch();
}
?>

Результат (при запуске и отправке SIGTERM):

Демон запущен. PID: 12345
Работаю...
Работаю...
Получен сигнал 15, завершаю работу.

Параллельное выполнение с помощью pcntl_fork

В CLI-режиме возможно создавать дочерние процессы для параллельной обработки. Функция pcntl_fork() возвращает 0 в дочернем процессе и PID потомка в родительском.

Пример
<?php
$pids = [];
for ($i = 1; $i <= 3; $i++) {
    $pid = pcntl_fork();
    if ($pid == -1) {
        die("Не удалось создать процесс");
    } elseif ($pid == 0) {
        // Дочерний процесс
        echo "Дочерний процесс $i начал работу (PID: " . getmypid() . ")\n";
        sleep(2);
        echo "Дочерний процесс $i завершён.\n";
        exit(0);
    } else {
        $pids[] = $pid;
    }
}
// Родитель ждёт завершения всех потомков
foreach ($pids as $pid) {
    pcntl_waitpid($pid, $status);
    echo "Родитель: процесс $pid завершён с кодом " . pcntl_wexitstatus($status) . "\n";
}
?>

Пример вывода:

Дочерний процесс 1 начал работу (PID: 12346)
Дочерний процесс 2 начал работу (PID: 12347)
Дочерний процесс 3 начал работу (PID: 12348)
Дочерний процесс 1 завершён.
Родитель: процесс 12346 завершён с кодом 0
Дочерний процесс 2 завершён.
Родитель: процесс 12347 завершён с кодом 0
Дочерний процесс 3 завершён.
Родитель: процесс 12348 завершён с кодом 0

Взаимодействие с внешними программами через proc_open

Функция proc_open() позволяет запустить внешнюю команду и управлять её потоками ввода-вывода. Это мощный инструмент для автоматизации.

Пример
<?php
$descriptorspec = [
    0 => ['pipe', 'r'],  // stdin
    1 => ['pipe', 'w'],  // stdout
    2 => ['pipe', 'w'],  // stderr
];

$process = proc_open('cat', $descriptorspec, $pipes);

if (is_resource($process)) {
    fwrite($pipes[0], 'Привет, proc_open!');
    fclose($pipes[0]);

    $stdout = stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    $stderr = stream_get_contents($pipes[2]);
    fclose($pipes[2]);

    $return = proc_close($process);

    echo "STDOUT: $stdout\n";
    echo "STDERR: $stderr\n";
    echo "Код возврата: $return\n";
}
?>

Результат:

STDOUT: Привет, proc_open!
STDERR: 
Код возврата: 0

Интерактивный ввод с историей через readline

Расширение readline предоставляет функции для построчного ввода с автодополнением и историей команд. Это удобно для создания собственных REPL-интерфейсов.

Пример
<?php
$history = [];
while (true) {
    $line = readline('php> ');
    if ($line === false || trim($line) === 'exit' || trim($line) === 'quit') {
        break;
    }
    readline_add_history($line);
    try {
        $result = eval($line);
        if ($result !== null) {
            var_dump($result);
        }
    } catch (Throwable $e) {
        echo "Ошибка: " . $e->getMessage() . "\n";
    }
}
?>

Запуск и ввод нескольких выражений:

php> 2 + 2
int(4)
php> strtoupper('hello')
string(5) "HELLO"
php> exit

Цветной вывод в консоли

С помощью ANSI-escape последовательностей можно добавлять цвета и стили к выводу в терминале.

Пример
<?php
function colorize($text, $color = 'white', $background = null, $bold = false) {
    $colors = [
        'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34,
        'magenta' => 35, 'cyan' => 36, 'white' => 37,
    ];
    $bg = null;
    if ($background && isset($colors[$background])) {
        $bg = $colors[$background] + 10; // фон = 40-47
    }
    $code = '';
    if ($bold) $code .= "\033[1;";
    else $code .= "\033[0;";
    $code .= $colors[$color];
    if ($bg) $code .= ";" . $bg;
    $code .= "m";
    return $code . $text . "\033[0m";
}

echo colorize('Красный текст', 'red') . "\n";
echo colorize('Зелёный жирный', 'green', null, true) . "\n";
echo colorize('Белый на синем фоне', 'white', 'blue') . "\n";
?>

Результат будет разноцветным в поддерживающем терминале.

Командная строка PHP (CLI) - comments

En
Php command line (php)