Задача:
Необходимо с интервалом в 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мб.
Что еще можно придумать ?
Память в районе 6мб процесса php-cgi.exe. Выше не поднимается 5-6мб.
Что еще можно придумать ?
Спустя 8 минут, 39 секунд (15.01.2012 - 14:11) Никита написал(а):
Если выпадала бы ошибка по памяти, она бы отражалась в логах верно ?
Спустя 52 секунды (15.01.2012 - 14:12) alex12060 написал(а):
я бы еще открыл "незакрываемое" соединение с mysql
так-же у тебя условие там стоит на выход, может оно отрабатывает? Пробуй завести свой лог.
Знаю, что не всегда работают "ini_set()"
тогда все будет более прозрачным.
Далее, очень странная идея делать демона на PHP.
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 - это же мощная штука.
sergeiss
Планировщик заданий на windows позволяет такое сделать хоть каждую минуту запускать скрипт
.
Я принципиально хочу понять причину падения цикла...
Спасибо, попробую... о удаче или неудаче сообщу.
А почему нельзя простенького демона на PHP ?
Мне кажется просто нужно понять причину отключения, а php - это же мощная штука.

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

Я принципиально хочу понять причину падения цикла...
Спустя 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));
}
}
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 раз вначале и все.
Нет, объявляется 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() тоже прописал.
Буду надеяться, что что-то да поможет выявить причину...
Я думаю дело даже не в соединении и БД, потому, что я делал такой же цикл и без запросов ми БД (проверка на существование файла, а не строки в БД).
Все равно отпадает...
Сейчас поставил на выполнение с поправками от alex12060... и mysql_ping() тоже прописал.
Буду надеяться, что что-то да поможет выявить причину...
Спустя 54 секунды (15.01.2012 - 15:22) Никита написал(а):
Кстати в стандартном планировщике минимальное время крона 5минут ... Это очень много для меня ... Нужно 10-20 секунд где-то.
Спустя 1 час, 17 минут, 30 секунд (15.01.2012 - 16:40) sergeiss написал(а):
Не знаю, как крон в Юниксе, а в Винде я могу установить запуск каждую минуту.
Другой вопрос в том, что ты хочешь "дёргать" БД каждые 10-20 секунд, при этом каждый раз делая COUNT. А надо ли это? Может быть, можно проще сделать как-то?
Что именно надо сделать? Давай вместе подумаем над более простым алгоритмом. У меня уже есть некоторые мысли, но я хотел бы сначала твой ответ услышать.
Другой вопрос в том, что ты хочешь "дёргать" БД каждые 10-20 секунд, при этом каждый раз делая COUNT. А надо ли это? Может быть, можно проще сделать как-то?
Что именно надо сделать? Давай вместе подумаем над более простым алгоритмом. У меня уже есть некоторые мысли, но я хотел бы сначала твой ответ услышать.
Спустя 32 минуты, 40 секунд (15.01.2012 - 17:12) Никита написал(а):
Периодически в таблицу processes поступают задания, которые необходимо запускать и обрабатывать.
То задание, которое сейчас обрабатывается имеет статус 1, остальные 0.
Мне необходим обработчик, который смотрит есть ли активное задание (статус=1), если нет, берет первое задание со статусом=0, присваивает статус=1, пускает в обработку...
И так циклично...
Нагрузки на бд почти никакой..., но вот хочется авто очереди и автовыполнения, а не включения скрипта, пока всю очередь обработает и вырубится...
В планировщике заданий минимальное время 15 минут. Это на Windows 2008 Server SP2.
То задание, которое сейчас обрабатывается имеет статус 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 запускаем заново этот же скрипт только новым процессом, а этот убиваем...
Вроде должно работать...
Как насчет того, что если действительно упор идет в ресурсы, то сделать конструкцию:
1) Запускаем "демона" так называемого, а внутри вместо "вечного" цикла цикл скажем до 20.
2) Как только доходит до 20 запускаем заново этот же скрипт только новым процессом, а этот убиваем...
Вроде должно работать...
Спустя 34 минуты, 41 секунда (15.01.2012 - 18:25) Никита написал(а):
Ajax - тоже думал использовать, но это уже на крайний случай... Там ведь нужен браузер открытый постоянно...
Хотелось бы все фоновым режимом...
А по табличке из бд можно уже аяксом смотреть что и как обрабатывается.
Хотелось бы все фоновым режимом...
А по табличке из бд можно уже аяксом смотреть что и как обрабатывается.

Спустя 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.
Смысл тот же, но твоя эта реализация мне не подходит т.к. у меня 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 написал(а):
Могу посоветовать совсем уж аццкий вариант. Поставить браузер опера. Открыть там страницу с твоим скриптом и правой кнопкой Обновлять каждые -> Задать интервал )))