#php #linux #laravel #ssh
Есть скрипт который может работать очень долго, более 1 часа, но из за fastcgi_read_timeout он тупо отрубается, и не может до конца выполнить работу. Как на хостинге увеличить, или обойти fastcgi_read_timeout? Хостинг reg.ru. Есть доступ к ssh Я нашел где ставится fastcgi_read_timeout, но у меня нет прав поменять его. Max_execution_time поменять могу, он стоит на 0, но это все равно не помогает. Выдается ошибка 500 internal server error Сейчас стоит fastcgi_read_timeout=300 Пробовал запускать скрипт через exec(), nohup, > /dev/null &. он проработал максимум 40 мин, т.е. так же отрубился
Ответы
Ответ 1
Столкнулся с аналогичной проблемой. Решил достаточно просто штатными средствами Laravel. Такие запросы нет смысла выполнять через браузер, оформил в виде задания (Job). Для выполнения задания, связанного с пакетной обработкой данных из БД, использовал chunkById()-обработку (а такие длинные запросы чаще всего связаны именно с пакетной обработкой базы и параллельным обращением к внешним вэб-API). В задании ограничил количество проходов chunk'а, что привело к вменяемому (до двух часов) времени выполнения задания. А для гарантированного завершения обработки всего пакета данных добавил генерирование задания по крону. Накладные потери времени на "пустую выборку" (когда все записи обработаны) составили 1 секунду на один запуск задания. Пример кода: namespace App\Jobs; use ... class TeletekaFilesCheckFilePresentJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected const CHUNK_COUNT = 100, CHUNK_MAX_RECORDS_PER_JOB = 300; /** * The number of seconds the job can run before timing out. * * @var int */ public $timeout = 14400; /** * Execute the job. * * @return void */ public function handle() { $start1 = microtime(true); $this->checkFilesFound(); $start2 = microtime(true); echo sprintf("\nFull runtime = %.3f sec. (%.3f sec. - check MediaObjects, %.3f sec. - other)\n", microtime(true) - $start1, $start2 - $start1, microtime(true) - $start2); } protected function checkFilesFound(): void { echo "Checking the availability of files on storage.\n"; $counter = 0; $filesCorrect = 0; $filesCount = DB::table('t_content_ext') ->where('files_state', TeletekaFile::FILES_STATE_NOT_CHECKED) ->count(); TeletekaFile::where('files_state', TeletekaFile::FILES_STATE_NOT_CHECKED) ->chunkById(self::CHUNK_COUNT, function ($files) use ($filesCount, &$counter, &$filesCorrect) { // Обработка выборки echo "\n", $counter += self::CHUNK_COUNT, ' of ', $filesCount, ' checked. ', $filesCorrect, ' files is correct.'; if ($counter >= self::CHUNK_MAX_RECORDS_PER_JOB) { echo "\nThe maximum number of items to process has been reached."; return false; } }); } }Ответ 2
set_time_limit(0) в начале скриптаОтвет 3
set_time_limit() — Ограничение времени выполнения скрипта. set_time_limit(0) - Если задан ноль, время выполнения неограничено. в вашем случае эту строку надо вставить в самом начале перед выполнением вашего скрипта. При вызове set_time_limit() перезапускает счетчик с нуля. Другими словами, если тайм-аут изначально был 60 секунд, и через 30 секунд после запуска скрипта будет вызвана функция set_time_limit(60), то скрипт будет работать максимум 90 секунд. Плюс ко всему. через 40 минут отрубается? нужно читать логи возможно у вас в коде возникает какая то ошибка и обрыв происходит по причине ошибки а не лимита.Ответ 4
Сам мучался недавно, надо писать cli и выводить данные уже. Я использовал исполнение команды https://www.php.net/manual/ru/function.passthru.php Повышение времени бесполезно, если скрипт неоптимизирован, это приводит к stackowerflow. Если это боевой, то службы сразу виснут. Помимо этого если скрипт монстрический нужно еще и оптимизировать, чистить переменные например. https://habr.com/ru/post/22799/ Как вариант выдачу еще можно фрагментировать, побить данные на 10 частей и качать последовательно, но лучше все таки на питончике подобное писать.
Комментариев нет:
Отправить комментарий