[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Не отрабатывает бесконечный цикл
Никита
Всем добрый день.
Задача:
Необходимо с интервалом в 15 секунд смотреть таблицу в бд на появление новых заданий.
Если заданий нет - ничего не делаем...
Если есть - получаем параметры из строки задания и запускаем необходимую функцию.
Для этого написал следующий код:

ini_set("display_errors","1");
ini_set("error_reporting",2047);
ini_set('log_errors', 'On');
ini_set('error_log', 'error.log');
ini_set('max_execution_time',0);

set_time_limit(0);
ignore_user_abort(1);

$conn = mysql_connect(_MYSQL_HOST,_MYSQL_USER,_MYSQL_PASS);
mysql_select_db(_MYSQL_DB,$conn);

do{
$c = 0;
list($c) = mysql_fetch_row(mysql_query("SELECT count(id) FROM processes WHERE proc='exit'",$conn));
if($c == 0){
exit(1);
}

/*делаем то, что надо*/
sleep(5);
}while(1);

Запуск скрипта:

pclose(popen('start /b php-cgi -f script.php',"r"));

Проблема в том, что скрипт не работает "вечно", а максимум 3,5 часа.
Где можно еще что-то поправить или изменить параметры php, чтобы работал до тех пор, пока не отключу (удаление строки exit из процессов)?

P.S OS Windows Server 2008.



Спустя 1 минута, 54 секунды (15.01.2012 - 13:55) alex12060 написал(а):
а что в логе пишет?
все ничего, но думаю, что тебе нужно позаботиться о вычистке памяти, потому что может копиться и потом выпадать с ошибкой о лимите памяти.

Спустя 7 минут, 18 секунд (15.01.2012 - 14:03) Guest написал(а):
Ошибок нет.
Память в районе 6мб процесса php-cgi.exe. Выше не поднимается 5-6мб.
Что еще можно придумать ?

Спустя 8 минут, 39 секунд (15.01.2012 - 14:11) Никита написал(а):
Если выпадала бы ошибка по памяти, она бы отражалась в логах верно ?

Спустя 52 секунды (15.01.2012 - 14:12) alex12060 написал(а):
я бы еще открыл "незакрываемое" соединение с mysql


mysql_pconnect(..)


так-же у тебя условие там стоит на выход, может оно отрабатывает? Пробуй завести свой лог.
Знаю, что не всегда работают "ini_set()"


register_shutdown_function('funcname');

function funcname() {
$error = get_last_error();

// тут самостоятельный лог
}


тогда все будет более прозрачным.

Далее, очень странная идея делать демона на PHP.

Спустя 4 минуты, 45 секунд (15.01.2012 - 14:17) sergeiss написал(а):
Я другое не понял. А почему бы не запускать этот скрипт через "плановые задачи" (аналог юниксового крона)? Названия могут быть немного разными, но в разных версиях Винды эта хрень есть и работает исправно. Надо только будет сделать контроль - не работает ли еще предыдущая версия скрипта в момент текущего запуска. Но это не сложно осуществить.
И работать будет более надежно, чем "вечный" скрипт.

Спустя 13 минут, 21 секунда (15.01.2012 - 14:30) Guest написал(а):
alex12060
Спасибо, попробую... о удаче или неудаче сообщу.
А почему нельзя простенького демона на PHP ?
Мне кажется просто нужно понять причину отключения, а php - это же мощная штука. wink.gif

sergeiss
Планировщик заданий на windows позволяет такое сделать хоть каждую минуту запускать скрипт smile.gif .
Я принципиально хочу понять причину падения цикла...

Спустя 7 минут (15.01.2012 - 14:37) Guest написал(а):
alex12060

А предложенную тобой конструкцию написать в начале кода или выполнять в каждой итерации цикла ?


ini_set("display_errors","1");
ini_set("error_reporting",2047);
ini_set('log_errors', 'On');
ini_set('error_log', 'error.log');
ini_set('max_execution_time',0);

set_time_limit(0);
ignore_user_abort(1);

$conn = mysql_pconnect(_MYSQL_HOST,_MYSQL_USER,_MYSQL_PASS);
mysql_select_db(_MYSQL_DB,$conn);

register_shutdown_function('funcname');

function funcname() {
$error = get_last_error();
if(!empty($error)){ file_put_contents('C:\inetpub\wwwroot\files\daemon\shutdown.log',$error);
}
}


for($i=0;;$i++){
$c = 0;
list($c) = mysql_fetch_row(mysql_query("SELECT count(id) FROM processes WHERE proc='exitt'",$conn));
if($c == 0){
exit(1);
}

/*необходимый код*/
sleep(5);
}


Правильно ?

Спустя 7 минут (15.01.2012 - 14:44) Никита написал(а):
Ругается на:
get_last_error();

Поискал ... нашел error_get_last();

Тут изменил немного... запущу проверю...
register_shutdown_function('funcname');

function funcname() {
$error = error_get_last();
if(!empty($error)){ file_put_contents('shutdown.log',serialize($error));
}
}

Спустя 7 минут, 25 секунд (15.01.2012 - 14:52) alex12060 написал(а):
да, напутал. Думаю, сериализацию делать не надо, достаточно запихать туда необходимые вещи.
Нет, объявляется 1 раз вначале и все.

Спустя 13 минут, 22 секунды (15.01.2012 - 15:05) killer8080 написал(а):
Перед mysql_fetch_row попробуй добавить mysql_ping(). Возможно все таки отваливается коннект.

Спустя 16 минут, 15 секунд (15.01.2012 - 15:21) Никита написал(а):
killer8080

Я думаю дело даже не в соединении и БД, потому, что я делал такой же цикл и без запросов ми БД (проверка на существование файла, а не строки в БД).
Все равно отпадает...
Сейчас поставил на выполнение с поправками от alex12060... и mysql_ping() тоже прописал.

Буду надеяться, что что-то да поможет выявить причину...

Спустя 54 секунды (15.01.2012 - 15:22) Никита написал(а):
Кстати в стандартном планировщике минимальное время крона 5минут ... Это очень много для меня ... Нужно 10-20 секунд где-то.

Спустя 1 час, 17 минут, 30 секунд (15.01.2012 - 16:40) sergeiss написал(а):
Не знаю, как крон в Юниксе, а в Винде я могу установить запуск каждую минуту.


Другой вопрос в том, что ты хочешь "дёргать" БД каждые 10-20 секунд, при этом каждый раз делая COUNT. А надо ли это? Может быть, можно проще сделать как-то?

Что именно надо сделать? Давай вместе подумаем над более простым алгоритмом. У меня уже есть некоторые мысли, но я хотел бы сначала твой ответ услышать.

Спустя 32 минуты, 40 секунд (15.01.2012 - 17:12) Никита написал(а):
Периодически в таблицу processes поступают задания, которые необходимо запускать и обрабатывать.
То задание, которое сейчас обрабатывается имеет статус 1, остальные 0.
Мне необходим обработчик, который смотрит есть ли активное задание (статус=1), если нет, берет первое задание со статусом=0, присваивает статус=1, пускает в обработку...
И так циклично...
Нагрузки на бд почти никакой..., но вот хочется авто очереди и автовыполнения, а не включения скрипта, пока всю очередь обработает и вырубится...
В планировщике заданий минимальное время 15 минут. Это на Windows 2008 Server SP2.

Спустя 19 минут, 58 секунд (15.01.2012 - 17:32) sergeiss написал(а):
Цитата (Никита @ 15.01.2012 - 18:12)
Периодически в таблицу processes поступают задания...

Сам запуск таких задач, как ты это описал - это больше не для ПХП задача. Тут скорее какой-то сервис получается.

Если очень хочется именно на ПХП сделать, то можно еще поднапрячь аякс. Тогда можно будет сделать сразу всё, что ты хочешь, плюс красивый визуальный контроль. Естественно, будет нужен и браузер. Но ежели у тебя сервер - Винда, то браузер - не проблема.

Спустя 18 минут, 15 секунд (15.01.2012 - 17:51) Никита написал(а):
Пришла идея...
Как насчет того, что если действительно упор идет в ресурсы, то сделать конструкцию:
1) Запускаем "демона" так называемого, а внутри вместо "вечного" цикла цикл скажем до 20.
2) Как только доходит до 20 запускаем заново этот же скрипт только новым процессом, а этот убиваем...

Вроде должно работать...

Спустя 34 минуты, 41 секунда (15.01.2012 - 18:25) Никита написал(а):
Ajax - тоже думал использовать, но это уже на крайний случай... Там ведь нужен браузер открытый постоянно...
Хотелось бы все фоновым режимом...
А по табличке из бд можно уже аяксом смотреть что и как обрабатывается. smile.gif

Спустя 1 минута, 50 секунд (15.01.2012 - 18:27) killer8080 написал(а):
Никита
Цитата (Никита @ 15.01.2012 - 16:51)
1) Запускаем "демона"

типа такого?
!#usr/bin/php
<?php

declare (ticks = 1);

$stop_server = false;

function sig_handler($signo){
global $stop_server;
if($signo == SIGTERM)
$stop_server = true;
}
//регистрируем обработчик
pcntl_signal(SIGTERM, "sig_handler");

$child_pid = pcntl_fork();

$child_pid && die();

posix_setsid();

file_put_contents('/tmp/my_pid_file.pid', getmypid());

while (!$stop_server) {
//делаем что-то
sleep(5);
}

Спустя 15 минут, 50 секунд (15.01.2012 - 18:43) Никита написал(а):
killer8080

Смысл тот же, но твоя эта реализация мне не подходит т.к. у меня Windows, а pcntl_fork работает только на unix.

Спустя 3 минуты, 11 секунд (15.01.2012 - 18:46) Никита написал(а):
Поставил на тест следующий скрипт script.php :

ini_set('log_errors', 'On');
ini_set('error_log', 'error.log');

set_time_limit(0);
ignore_user_abort(1);

$conn = mysql_connect(_MYSQL_HOST,_MYSQL_USER,_MYSQL_PASS);
mysql_select_db(_MYSQL_DB,$conn);

function funcname() {
$error = error_get_last();
if(!empty($error)){
file_put_contents('shutdown.log',serialize($error));
}
}


register_shutdown_function('funcname');
$num_cycles = 20;
for($i=0;$i<=$num_cycles;$i++){
mysql_ping($conn);
list($c) = mysql_fetch_row(mysql_query("SELECT count(id) FROM processes WHERE proc='exit'",$conn));
if($c == 0){
exit(1);
}else{
if($i == 20){
pclose(popen('start /b php-cgi -f script.php',"r"));
exit(1);
}else{
mysql_query("UPDATE processes SET date='".date("Y-m-d H:i:s")."' WHERE proc='exit'",$conn);
sleep(5);
}
}
}


Спустя 1 день, 17 часов, 59 минут, 18 секунд (17.01.2012 - 12:45) Zhandos написал(а):
Могу посоветовать совсем уж аццкий вариант. Поставить браузер опера. Открыть там страницу с твоим скриптом и правой кнопкой Обновлять каждые -> Задать интервал )))
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2025 Invision Power Services, Inc.