Исполняемый PHP-файл: настройка, запуск и администрирование
Исполняемый файл PHP: настройка и запуск скриптов в режиме командной строки
Основное решение: использование shebang и прав на выполнение
Для запуска PHP-скрипта как самостоятельного исполняемого файла в среде Linux/Unix достаточно добавить в первую строку скрипта шебанг (shebang) с указанием пути к интерпретатору PHP и выставить бит выполнения. После этого файл можно запускать напрямую: ./script.php.
#!/usr/bin/php
<?php
echo "Hello, World!\n";
?>
выполнение файлов php (выполнение файлов php)
Шаги настройки:
- Создать файл, например
hello.php, с содержимым выше. - Установить права:
chmod +x hello.php. - Запустить:
./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. Скрипт исполняется как команда.