gzhegow
@gzhegow
aka "ОбнимиБизнесмена"

Cron, wget и отгрызание части файла — почему опять стэк может не работать?

Здравствуйте, столкнулся со странной ситуацией - написан скрипт, который при прямом заходе на URL отрабатывает в 100% случаев правильно.
Если его запустить из консоли сервера через wget - все тоже работает отлично.
Но стоит его поставить на cron с использованием isp-manager, то он иногда отрабатывает как надо, иногда с ошибками, иногда вообще не отрабатывает, а иногда отрабатывает половина, а остальная часть потом, ломая всю логику программы.

Скрипт вкратце работает так:
1. Считать файл прайс-листа командой file() в массив и сохранить копию файла
2. Забрать 100 строк, которые определены как продукты, и любое количество других, которые были между ними.
3. С этой сотней строк работаем - записываем в mysql по очереди как положено
4. Оставшиеся данные сохранить в исходный файл
5. При следующем запуске файл уже не копировать, а только считывать

Поскольку каждый вызов файла привязан к конкретному прайс-листу, то для того чтобы за один раз обрабатывать весь скрипт - используется header("Location: ") сам на себя и функция die(), при этом передаются параметры - размер шага и имя файла, чтобы избежать случайного разбора "не того файла".

Если запускать скрипт через браузер - отрабатывает в 100% случаев отлично, файл себе грызется, данные заливаются.
Если запустить его через shell wget --max-redirect=1000 "url?params" - все тоже работает отлично
Стоит его повесить на Крон

В логах shell ничего, как и должно быть
В логах файла, когда он отработал криво - все как и должно быть, отчет, надпись "скрипт завершен"
А вот в логах cron он ловит 504 Timeout от сервера nginx, и возможно тут происходит какая-то бадяга (наверное)

То есть браузером он тоже ловит 504, но выполняться скрипт продолжает.
А вот по крону такое ощущение, что он не дожидаясь окончания скрипта - переходит по редиректу и запускает второй поток выполнения, забывая, что первый еще делается.

По итогу наблюдаются такие ситуации:
1. Файл скопировался, все загрузилось, но оригинал не изменяется. Думал права, поставил 666, то же самое
2. Файл скопировался, отгрызли кусочек, закачали этот кусочек и все, колом стал
3. Файл скопировался, все отработало отлично, но через некоторое время в папке снова появляется один из кусков оригинала, как будто он сначала выполнился, а потом заканчивает работу асинхронно
и подобные чудеса

Кто подскажет, как это дебажить, почему возможны ошибки?

Я не пробовал запускать через shell командой "php" с атрибутами, пока только wget. Но интересно что при прямом запуске все работает, а по крону - часть файлов загрузило, другие не загрузило. В одной папке отработало, а в соседней точно такой же код выдает одну из вышеуказанных ошибок

Самое обидное, что рядом работает по такому же принципу еще десяток кронов, и они работают отлично, потому что там нет "отгрызания файла", а просто запоминается номер строки и ид-шники категорий в базе данных, что создает кучу связей и невозможность дорабатывать скрипт - там 10 тыщ строк кода, в моем случае 900.
  • Вопрос задан
  • 551 просмотр
Пригласить эксперта
Ответы на вопрос 1
gzhegow
@gzhegow Автор вопроса
aka "ОбнимиБизнесмена"
Вероятный ответ напишу, пока не отмечаю:
1. В коде имелась функция register_shutdown_function() которая писала логи при завершении программы
2. После редиректа происходил вызов статического метода Import::end() который добавлял в лог "Спасибо, скрипт все" и вызывал exit();
3. Несмотря на это пришлось разобраться в консоли дебиана и поиграть с командами top/free, поизучать логи, посмотреть, что все вроде бы работает...
4. На мысли наводила только надоедающая "Mysql server is gone away", но казалось бы - почему?

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

С другой стороны сам скрипт работает с Редиректом, и несмотря на то, что транзакция закрывается и от сервера отключаемся - что-то шло не так.

Когда я вывел процессы через top, и посмотрел оперативку через free - оказалось оперативки нет, более того - после отключения сервера mysql - он даже не захотел включаться, недостаточно памяти.

Память увеличил на виртуалке, и все пошло правильно работать. Тут то и пришла идея - а что если. Вывел top и увидел ужас- на меня одного запущено 32 апача, как будто он вообще не завершал процессы.

А ведь функция exit() все таки есть. Видимо где-то происходит косяк.

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

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы