nginx и cron

Главные вкладки

Аватар пользователя ingumsky@drupal.org ingumsky@drupal.org 22 ноября 2010 в 23:49

Добрый день, коллеги!

Неожиданно обнаружил проблему с кроном. Дело в том, что на днях мы совершили перевод сайта с nginx+apache на чистый nginx. Всё работает замечательно, и сайт стал лучше справляться с нагрузкой, но сегодня я заметил, что в статусе (example.net/admin/reports/status) у меня светится:
«Последний запуск 5 дней 18 часов назад.

Крон давно не запускался. Подробная информация находится в документации по настройке, на странице настройки работы крона. Вы можете запустить выполнение регулярных процедур (cron) вручную.»

Если я пытаюсь запустить крон вручную (example.net/admin/reports/status/run-cron), выдаёт ошибку запуска крона. При этом из консоли wget мне бодро рапортует о том, что example.net/cron.php — 200.

В логе Друпал (example.net/admin/reports/dblog) вижу информацию о последних попытках запуска крона:
Все запуски вручную отмечены предупреждением: «Попытка перезапуска выполнения регулярных процедур (cron) в то время, как они уже выполняются».
Все регулярные запуски (ежечасовые) за последние дни идут с ошибкой: «Время выполнения регулярных процедур превысило час, скорее всего это зависание».

Подскажите, пожалуйста, с чем это может быть связано и как побороть? Когда работал с Апачем (ещё те самые 5 дней 18 часов назад), проблем с кроном не было вообще.

Комментарии

Аватар пользователя Mirocow Mirocow 23 ноября 2010 в 0:27

"<a href="mailto:ingumsky@drupal.org">ingumsky@drupal.org</a>" wrote:

Это переменная сама восстановится когда отработает крон. Это флаг работы cron.
сорь ввел в заблуждение. Эта переменная cron_last конечно.

Аватар пользователя ingumsky@drupal.org ingumsky@drupal.org 23 ноября 2010 в 0:35

"Mirocow" wrote:
Это переменная сама восстановится когда отработает крон. Это флаг работы cron.
сорь ввел в заблуждение. Эта переменная cron_last конечно.

Семафор — это время, за которое должен отработать крон, как я понимаю. Мне интересно, каким образом восстанавливается она.

Аватар пользователя ingumsky@drupal.org ingumsky@drupal.org 23 ноября 2010 в 1:00

"Ромка" wrote:
Попробуй удалить переменную cron_semaphore:

Почитал drupal_cron_run, удалил cron_semaphore. После этого крон отработал нормально. Спасибо!

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

Аватар пользователя gorr gorr 23 ноября 2010 в 2:05

Все просто - друпал, когда запускает крон, вешает эту переменную, чтобы если вдруг кто-то опять попробует запустить крон во время того, как он уже запущен, у него ничего не вышло. А потом, в конце выполнения крона он ее сам удаляет. Но если крон не успевает выполниться за отведенное время, то переменная не сбрасывается и уже запустить крон не удается, пока ее не сбросишь сам.

Аватар пользователя Mirocow Mirocow 23 ноября 2010 в 2:52

cron_last - а эта переменная сигнализирует о последнем запуске и если ее удалить то cron drupal будет думать, что cron не был запущен ни разу.

Аватар пользователя ingumsky@drupal.org ingumsky@drupal.org 25 ноября 2010 в 0:55

"gorr" wrote:
Все просто - друпал, когда запускает крон, вешает эту переменную, чтобы если вдруг кто-то опять попробует запустить крон во время того, как он уже запущен, у него ничего не вышло. А потом, в конце выполнения крона он ее сам удаляет. Но если крон не успевает выполниться за отведенное время, то переменная не сбрасывается и уже запустить крон не удается, пока ее не сбросишь сам.

Спасибо! Значит я всё правильно понял.
"Mirocow" wrote:
cron_last - а эта переменная сигнализирует о последнем запуске и если ее удалить то cron drupal будет думать, что cron не был запущен ни разу.

Спасибо. Да, с этим я разобрался, когда смотрел drupal_cron_run.

Аватар пользователя ingumsky@drupal.org ingumsky@drupal.org 25 ноября 2010 в 1:00

Тем не менее, проблемы с кроном никуда не делись. В том смысле, что мне удалось его тогда запустить руками, а автоматом он всё равно не запускается — сейчас в статусе у меня написано, что он не запускался два дня -(

Симптомы всё те же — есть семафор, крон не отрабатывает...

Аватар пользователя gorr gorr 25 ноября 2010 в 10:14

Значит много на крон задач навешано, например у меня производилась отправка рассылки и слишком много за раз писем пытался отправить, а time_limit установить в 0 не давали.
Нужно смотреть, какая операция времязатратная.
В итоге просто написал маленький модуль semaphore_drop с хуком init, чтобы сбрасывать этот семафор при зависании:
<?php

/**
* My cron semaphore deleting for cron is often timed out.
*/
function semaphore_drop_init() {
$semaphore = variable_get('cron_semaphore', FALSE);
if($semaphore && (time() - $semaphore > 600)) {
variable_del('cron_semaphore');
}
}
?>

Аватар пользователя Ромка Ромка 25 ноября 2010 в 10:28

Вероятно какой-то из hook_cron'ов работает некорректно. В таком случае на его выполнении обработка Друпалом хук_кронов прекращается, переменная cron_semaphore не удаляется и в следующий раз крон не запускается. Еще раз удали эту переменную, затем в файле includes/module.inc в функцию module_invoke_all после строки:
<?php
$function = $module .'_'. $hook;
?>
добавь:
<?php
if ($hook == 'cron') {
watchdog('cron_debug', 'trying to run ' . $function);
}
?>
Затем запусти крон и смотри в дблог (или сислог, в общем туда, куда у тебя Друпал пишет свой лог), последняя запись cron_debug будет содержать имя глючного hook_cron. Его нужно будет или исправить, или выключить. Ну и потом не забыть отменить все изменения в module.inc.

Аватар пользователя ingumsky@drupal.org ingumsky@drupal.org 25 ноября 2010 в 16:06

"Ромка" wrote:
Вероятно какой-то из hook_cron'ов работает некорректно. В таком случае на его выполнении обработка Друпалом хук_кронов прекращается, переменная cron_semaphore не удаляется и в следующий раз крон не запускается. Еще раз удали эту переменную, затем в файле includes/module.inc в функцию module_invoke_all после строки:

Судя по всему, виноват search_cron, который отправляет на переиндексацию все имеющиеся модули.

<?phpforeach (module_list() as $module) {
   module_invoke($module, 'update_index');
}?>

Я только не могу понять, с чем могут быть связаны перебои в его работе, если раньше (до переезда на nginx) всё работало нормально. Может ли это быть связано с тем, что c лимитами php (мы перекомпилировали php)? В php.ini (cli) лимит выставлен на 256 мегабайт.

"gorr" wrote:
В итоге просто написал маленький модуль semaphore_drop с хуком init, чтобы сбрасывать этот семафор при зависании:

Да, в принципе, тоже вариант. Но сейчас, как я посмотрю, у меня семафор всё же удаляется, но времени на обработку крона всё равно не хватает. Я ещё сообразил, что у меня крон дёргается с трёх разных серверов — пережитки старых хостингов, где не было доступа к крону, поэтому надо было вешать wget в крон другого сервака.
"Goodboy" wrote:
Или попробуйте  supercron

Почитаю, спасибо!

Аватар пользователя Node_one Node_one 28 февраля 2011 в 17:59

"Ромка" wrote:

Попробуй удалить переменную cron_semaphore:

<?php
variable_del('cron_semaphore');
?>

Может быть поможет

Извините, где ввести и выполнить этот код?

Аватар пользователя Node_one Node_one 1 марта 2011 в 14:44

А, надо поместить его в корневой каталог сайта и выполнить аналогично
mysite.ru/cron.php?

Вот, нагуглил:

Совет: как сделать скрипт использующий Drupal API | Drupal в рунете http://www.drupal.ru/node/170

Прислано: axel вт, 29/06/2004 - 16:09 Другие статьи по теме: * Программирование

Бывает возникает необходимость сделать быстро какой-нибудь скрипт, но нет нужды оформлять его в виде модуля. Однако обращаться к базе или использовать какие-то функции Drupal при этом удобно. Чтобы PHP-скрипт использовал API Drupal следует написать его так:

<?php

include_once "includes/bootstrap.inc";
include_once 
"includes/common.inc";
// далее можно писать скрипт, теперь вам доступны друпаловские функции
// ...
?>
Аватар пользователя goodboy goodboy 1 марта 2011 в 14:48

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