Как запустить php скрипт в фоне?

Ссылка скопирована
PHP
25 марта 2026 1 ответ

Есть кнопка на странице по нажатию на которой надо чтобы пользователь мог дальше продолжать работу, пока в фоне происходит выполнение скрипта.

Это реализовано путем открытия новой вкладки по нажатию на кнопку, в которой выполняется скрипт, а по завершении вкладка закрывается.
Но я столкнулся с проблемой, что выполнение скрипта может быть довольно долгим и по истечении 60с таймаута nginx принудительно завершает выполнение скрипта. Повышать таймаут не вариант.

Как сделать так, чтобы скрипт выполнялся в фоне?

Дополнительно:

Как вариант это очередь + крон. Пользователь нажимает кнопку, записывается задание, пусть даже в файл, крон дергает скрипт на проверку заданий, выполняет и удаляет файл

  • Сначала сделайте вывод из скрипта каждые 5-10-15-30 секунд, по вкусу. Разумеется с очисткой всех возможных буферов, что бы данные браузеру точно уходили сразу. Если не поможет - тогда да, мудрить с очередями и cron-ами.
  • по истечении 60с таймаута nginx принудительно завершает выполнение скрипта

    Nginx завершать скрипт не может и не делает этого. Он просто перестаёт ждать от него ответа, но сам скрипт при этом продолжает выполняться, если внутри него самого или условного FPM нет другого таймаута.

  • exec(“nohup php file.php >/dev/null 2>&1 &");
  • Дмитрий, а параметры как прокинете?)
  • WitER, $argv?
  • Дмитрий, простите, это было очевидно, как именно по вашему мнению это должно выглядеть?
  • WitER,
    nohup php file.php 1231 12312 12321 234234 vasya > /dev/null 2>&1 &

    nohup php file.php 1231 12312 12321 234234 vasya > /dev/null 2>&1 &

  • WitER, я чуток теряюсь в догадках что вы мне хотите сказать.
  • Дмитрий, пытаюсь сказать, что, как минимум, стоило упомянуть о том, что никакие данные пришедшие от пользователя туда пихать не стоит - получим вполне себе прикольный шелл.
    Более того, есть сомнения что у воркера fpm будет достаточно прав в системе, чтобы дернуть эту команду.
    Первый комментарий в ветке даёт самое верное решение - кинуть в очередь и обработать правильно запущенным скриптом.
  • WitER, ну мне как минимум неизвестны данные которые приходят, от кого они приходят и как что мы с ними будем делать. очередь это круто, а можно и отдельного демона накостылить который будет получать данные в лоб и спавнить воркера под эту задачу.

    Однако судя по постановке вопроса - мой вариант автором может быть реализован, а вариант даже с очередью в данный момент вряд ли. Если бы вы при этом просто написали что стоит задуматься об экранировании данных - я бы с вами согласился на все 100%, ибо как то считаю это естественным - а тут стоило бы действительно указать. зря вы начали эти игры в пилу.

    З.Ы. Какую команду? nohup?

  • Дмитрий, никто с вами не играет, вы прекрасно понимаете, что недосказанность порождает недопонимание и как итог автор вопроса сам того не понимая может запилить себе же яму.
    з.ы. вызов php или чего-либо еще, а может и exec оказаться в disable_functions.
  • WitER, прекрасно понимаю. и сказал - что если бы вы просто написали что обязательно надо добавить экранирование - я тут же бы с вами согласился. но вы почему то начали играть в вопросы.

    з.ы. и при этом человеку дадут поставить какой нибудь rabbitmq, что бы с очередями играться? ну такое себе предположение.

  • Ответы:

    Как отдать ответ клиенту и продолжить выполнение долгого скрипта?

    или так.

    <?php ignore_user_abort(true); set_time_limit(0); ob_start(); header('Connection: close');  header('Content-Length: '.ob_get_length()); // можно добавить http статус подходящий ob_end_flush(); ob_flush(); flush(); // дальше запуск run_havy_task();

    <?php ignore_user_abort(true); set_time_limit(0); ob_start(); header('Connection: close'); header('Content-Length: '.ob_get_length()); // можно добавить http статус подходящий ob_end_flush(); ob_flush(); flush(); // дальше запуск run_havy_task();

    оба варианта предполагают, что есть отдельный способ получения результатов выполнения запущенной задачи.

    UPD: после критики в комментариях, поясню.
    Предложенное мной решение - примитивный способ сказать web серверу вернуть клиенту ответ и после этого продолжить выполнение скрипта.
    При этом ресурсы ресурсы сервера не будут освобождены пока функция run_havy_task не закончит работу. Можно использовать fastcgi_finish_request - но она не на 100% гарантирует завершение процессов.
    Таким образом, если до этого вы не переживали о ресурсах выделенных на выполнение "тяжелого" скрипта, то можно продолжать и так - запихнуть всё тяжелое в внутрь run_havy_task.
    Но лучше будет "тяжелую" часть обрабатывать в отдельных процессах. Например, одним из способов из комментариев к вопросу или из другого ответа, ссылку на который я дал в начале своего.

    • Ну вы бы хоть какой нибудь fastcgi_finish_request добавили что бы не ждать таймаута.

      Ну и решение так себе - забрать под себя процесс php-fpm.

    • Дмитрий, run_havy_task_and_release_fpm();
    • iljaGolubev, это как вы release_fpm будете делать? Воркер nginx то вы через finish отправите других обслуживать, а с fpm вы в этой конструкции как это сделаете?
    • да что хотите, то и делайте. не моя функция.
      вопрос Как запустить php скрипт в фоне? - ответ.
    • iljaGolubev, это не запустить процесс в фоне. это продолжить юзать процессы fpm пока вы не выжрете весь пул fpm и nginx будет весело отвечать всем новым 502. А без finish_request это еще выжрать всех воркеров nginx. Такой вариант убийства сервера без регистраций и смс
    • Дмитрий,
      fastcgi_finish_request — Flushes all response data to the client
      ///
      ob_end_flush();
      ob_flush();
      flush();

      я не на 100% уверен, что это одно и тоже. а вы?

    • iljaGolubev, стоит внимательно прочитать документацию помимо того что finish делает flush она еще и закрывает request сервера который обращается к fpm. Говорит ему финита ля комедия - иди работай с другими.

      and finishes the request. This allows for time consuming tasks to be performed without leaving the connection to the client open.

      В вашем случае - nginx будет сидеть ждать когда у него таймаут на ожидание сработает.

    • run_havy_task(){ // exec nohup // rabbit // wtf exit(0); }

      run_havy_task(){ // exec nohup // rabbit // wtf exit(0); }

    • iljaGolubev, и? пока run_havy_task не будет выполнена - до exit ни хрена не дойдет. И процесс php-fpm будет этим заниматься. Вы через chatgpt что ли варианты ищете?
    • Дмитрий,
      вы и правда не понимаете ?
      run_havy_task(){ exit(0); }
      всё. выполнена. в чем проблема то? вопрос бы не в том как не повесить сервер при "долгих" скриптах, а как не нарваться на истечение таймаута от nginx не меняя его.
    • iljaGolubev, нет не понимаю. такой конструкции в php нет. я предположил что вы опечатались - но судя по всему нет.

      вопрос как выполнить скрипт в фоне. ваше решение не решение в фоне. ваше решение - а давайте грохнем сервак. ну вообщем то почему нет - нахрен он нужен

    • Дмитрий, ну а я вас не понимаю.
      Автор:

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

      Дмитрий:

      а давайте грохнем сервак. ну вообщем то почему нет - нахрен он нужен

      Я: а пофиг!

    • iljaGolubev, ну вот стоит в верху вашего решения и дописать "а давайте грохнем сервак ибо мне пох". Тогда решение примет законченый вид, и глядишь автор вопроса посмотрит на другие решение которые ему в комментах посоветовали.
    • iljaGolubev, тупой ответ.
    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Виктор Sys Ответ

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

    1. Использование командной строки:
    Вы можете запустить PHP скрипт в фоне, используя команду `php` в терминале и добавив амперсанд `&` в конце команды. Например:

    php script.php &

    php script.php &

    2. Использование функции `exec`:
    Вы также можете использовать функцию `exec` в PHP для запуска скрипта в фоне. Например:

    exec('php script.php > /dev/null 2>&1 &');

    exec('php script.php > /dev/null 2>&1 &');

    3. Использование `nohup`:
    `nohup` - это утилита, которая позволяет запустить процесс в фоне и не зависеть от текущего терминала. Например:

    nohup php script.php > /dev/null 2>&1 &

    nohup php script.php > /dev/null 2>&1 &

    4. Использование `screen`:
    `screen` - это утилита, которая позволяет создавать виртуальные терминалы в Linux. Вы можете запустить скрипт в фоне в новом экране. Например:

    screen -S myscript php script.php

    screen -S myscript php script.php

    Выберите подходящий для вас способ в зависимости от ваших потребностей и требований к процессу запуска PHP скрипта в фоне.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно