В моем учебнике приводится такой пример: PHP: <?php ##Использование popen() . //Запускаем процесс (параллельно работе сценария) режиме чтения. $fp = popen("usr/sbin/sendmail -t -i", "wb"); //Передаем процессу тело письма в стандартный входной поток. ........ Далее идет коментарий:"...По команде popen() запускается указанная в первом параметре программа, причем выполняется она параллельно сценарию..." Вот с этим ПАРАЛЛЕЛЬНО у меня неувязочка и выходит... мне нужно запустить другой скрипт, который от команды sleep() вздремнет немного, а затем выполнится. Я так понимаю, что при параллельном выполнении основной скрипт, вызвавший команду popen(), не должен дожидаться окончания выполнения вызываемого скрипта и работать дальше... но у меня ждет выполения... Как заставить скрипт выполнится параллельно?
опишите причину необходимости такого поведения и ваш случай можно реализовать, вопрос лишь в том, стоит ли овчинка выделки
Суть всего вот в чем: мне нужно организовать многопоточность работы с БД MySQL. Пока дело не доходит до редактирования записи, проблем не возникает. Проблема возникает, когда нужно отредактировать запись: скрипт генерирует пользователю страницу с исходными данными для редактирования, пользователь получает эту страницу, меняет данные и отправляет обратно на сервер для сохранения. Обычная блокировка таблицы LOCK TABLE не прокатывает, т.к. она автоматически завершается при завершении скрипта (в данном случае скрипта, генерирующего страницу с исходными данными). Я решил, что можно ставить метку (к примеру ID сессии и текущее время) в нужную строку - остальные скрипты, увидев эту метку должны будут ждать до окончания блокировки, пока получат право на редактирование данной записи. Ну а концом блокировки можно считать отправку и сохранение новых данных на сервере, либо переход по другой ссылке на странице. Вроде идея неплохая, но есть одно НО, а точнее два: а если пользователь просто грубо закроет (может даже убьет станицу через диспетчера ради эксперимента) или просто отвалится (отключили к примеру свет)? Тогда метку никто не снимет и никто не получит право на редактирование данной записи никогда! Выходом можно посчитать следующее: скрипт, генерирующий первоначальную страницу, также запускает разовую проверку времени последнего обновления - если оно превышает некий интервал, то значит, что пользователь по каким-либо причинам больше не работает с данной записью и можно удалить метку. Поскольку заранее нельзя сказать, сколько по времени займет у пользователя редактирование данных (может он откроет запись для редактирования и пойдет ублажать целый гарем), то приходится немного расширить скрипт: со страницы пользователя циклически отправляются команда на изменение времени последнего обновления записи, а также команда на очистку метки. Т.к. команды обе находятся на серваке и получает их сервер одновременно от пользователя (это можно гарантировать), то никакие события на стороне пользователя не приведут к глупой ситуации "вечно редактируемой записи". для этого мне надо сделать так, чтобы скрипт, выполняющий проверку последнего времени обновления записи и при необходимости убирающий метку, получал команду на выполнение, но не задерживал основной сценарий. Можно делать и не скриптом, а, скажем, EXE-шником, но проблема остается та же... все функции, которые я использовал, ждут выполнения дочернего процесса
вы сами себе противоречите. если вы решили использовать в качестве метки id сессии, то и снятие лока должно выполняться по обновлении вашего материала ИЛИ по разрушению сессии (смотря что случится раньше). попросить БД залипнуть, пока юзер не передумает/не сделает свою работу - это худший их всех вариантов, который можно вообще придумать
я не спец по работе с сессиями, а точнее вообще впервые их затронул... и то с целью использовать не совсем по назначению... Если я начинаю новую сессию в скрипте getData.php, то сколько эта сессия будет существовать? доживет ли она до скрипта saveData.php, если пользователь будет думать несколько часиков? Что с ней будет, если пользователь отвалится из-за ЧП или по своей милости (к примеру введет в адресную строку новый адрес и нажмет Enter) - ведь сессия сразу в этом случае скорее всего не угаснет, а будет прибита через значительное время автоматически, а запись должна освободиться максимально быстро для редактирования. И в чем я себе противоречу? Если пользователь все еще на странице редактирования данных, то эта страница автоматически подает сигнал об этом и редактируемая запись доступна лишь ему. Если же пользователь больше не подает "признаков жизни", то имеющаяся у сервера команда уберет метку. Если пользователь дал сам команду, то сервер также уберет метку. Единственное слабое место, которое я в этом случае вижу - если сервак грохнется между сохранением данных и очисткой метки... Других противоречий я тут не вижу...
вам безразлично, когда конкретно должна быть оборвана сессия. пользователь открыл браузер, решил отредактировать статью - час думал, два думал, три думал... сессия отмерла, юзер отправляет результат. смотрим - сессии такой больше нет, метку стираем и видим, что пользователь хочет записать сообщение без предварительного резервирования, заворачиваем его с сообщением "вы не можете сейчас записать вашу статью, потому что превышен интервал ожидания. попробуйте еще раз". а со второй попытки у него получится, если больше никто статью не редактирует. во всех остальных случаях, метка будет обработана суперкорректно зы: если пользователь закрыл браузер, то сессия корректно завершилась
А как тогда обеспечить недоступность записи для редактирования в этом случае остальным пользователям? И если пользователь некорректно завершил сессию, то сколько по времени она еще будет существовать, пока завершится сама и освободит запись для редактирования? Ведь нужно, чтобы она освободилась как можно быстрее (в пределах 2-5 минут)
время жизни сессии - это настраиваемый параметр. есть некоторые тонкости с минимальным временем жизни. если интересует: http://habrahabr.ru/blogs/php/28418/
Не получается решить проблему вероятности перехвата права редактирования... Если идти по такой схеме: - внести идентификатор сессии в таблицу для обозначения занятой позиции, а потом получать другими пользователями этот идентификатор и проверять данную сессию на жизнеспособность - не существует, значит редактируем, а существует - ждем дальше то всю гармонию нарушает сборщик мусора - он через указанное время перебьет все сессии, хранящиеся во временном каталоге и у другого пользователя будет возможность перехватить право редактирования записи до того, как первый пользователь опять заявит свое право на внесение изменений. Если же сделать время жизни сессии большим, то в течение длительного времени после некорректного завершения работы запись останется недоступной...
http://ru2.php.net/manual/en/function.popen.php#92413 И где-то на php.net было и для линуха - лень искать.
Код (Text): start /B php {путь к файлу}\file.php "параметр 1" параметр_число "строковый параметр 2" Соответственно, параметров может быть сколько надо или не быть вовсе. Искать их в $_SERVER['argv']
Мдя... рано радоваться... в одном скрипте получилось... попытался перенести в другой - облом по всей усатой морде... PHP: <?php ...... $file = fopen('../forms/TTH.txt', 'w+b'); fwrite($file, "$Organization\n" . $TTH); fclose($file); //`start ../exe/TTH.exe`; //$commandString = 'start /b Z:\\home\\sitrans.ru\\www\\exe\\TTH.exe -attachment "c:\\temp\file1.txt"'; //$commandString = 'start /b Z:\\home\\sitrans.ru\\www\\exe\\TTH.exe -attachment'; $commandString = 'start /b Z:/usr/local/php5/php.exe Z:/home/sitrans.ru/www/php/test.php "888parampampam888"'; pclose(popen($commandString, 'r')); //`Z:/usr/local/php5/php.exe Z:/home/sitrans.ru/www/php/test.php`; echo "<div style='color: red; font-size: 50px; text-decoration: underline'>$hndl</div>\n"; //popen ('TTH.exe -t -i', "wb"); //require_once('../exe/run.php'); //$file = popen('../exe/TTH.exe', 'r'); echo $report . "\n\n\n" . "Файл для распечатки сохранен в Мои документы/TTH.xls "; ?> здесь без ожидания окончания выполнения запускается скрипт test.php - и действительно последняя отладочная команда echo выводит результат, не дожидаясь, пока проснется test.php В другой скрипт я перенес ту же команду без изменения, однако скрипт дожидается, пока test.php проснется и выполнится... Что я теперь не так ему сделал??? PHP: <?php session_start(); require_once ('DateToNumber.php'); require_once ('clear.php'); $link = mysql_connect('localhost', 'root', ''); mysql_select_db('SITRANS'); //$lock = mysql_query ("lock tables drivers write"); //echo "$lock<br /><br /><hr />"; $num = $_POST['num']; $currenttime = time(); $SID1 =SID; //$r1 = ''; mysql_query('lock tables drivers write'); $res = mysql_query("select * from drivers where ind=$num and session_id=''"); //$r1 .= mysql_num_rows($res) . "<hr />"; if (mysql_num_rows($res) == 0) { $res = mysql_query("select session_id from drivers where ind=$num"); $res = mysql_fetch_array($res); if ($res[0] != '') { echo 'Данную позицию в настоящее время использует другой пользователь.'; exit(); } } else { mysql_query("update drivers set session_id='$SID1', time=$currenttime where ind=$num"); //$r1 .= ("update drivers set session_id='$SID1', time=$currenttime where ind=$num"); } mysql_query('UNLOCK TABLES'); $res = mysql_fetch_array($res); $result = "<div style='text-align: center;'>Изменение данных водителя<div style='text-align: center; font-size: 25px; font-weight: bold'>$res[4]</div></div><br /><br />"; $result .= "<div align=center><table width=60% style='border-width: 1px; border-style: solid;'><tr><td width='50%' style='text-align: left; vertical-align: top;'>Водительское удостоверение</td><td style='text-align: left'><input type=text id='DriverLicense' value='$res[1]'"; $result .= "onBlur='CheckFormatDriverLicense ();' size=50/><br /><br />"; $result .= "</td></tr>"; $result .= "<tr><td style='text-align: left; vertical-align: top;'>Дата выдачи</td><td style='text-align: left'><input size=50 type=text id='DriverLicenseDate' value='$res[2]' "; $result .= "onChange='this.value = (this.value.replace(/[^\\d]+/g, \".\").replace(/\\.{2,}/g, \".\"))'/><br /><br /></td></tr>"; $result .= "<tr><td style='text-align: left; vertical-align: top;'>Кем выдан</td><td style='text-align: left'><input size=50 type=text id='GIBDD' value='$res[3]' /><br /><br /></td></tr>"; $result .= "<tr><td style='text-align: left; vertical-align: top;'>ФИО</td><td style='text-align: left'><input type=text id='NameDriver' size=50 value='$res[4]' /><br /><br /></td></tr>"; $result .= "<tr><td style='text-align: left; vertical-align: top;'>Телефон</td><td style='text-align: left'><input size=50 type=text id='TLPH' value='$res[5]'/><br /><br /></td></tr>"; $result .= "<tr><td colspan=2 style='text-align: center;'><input type=button value='Сохранить' onClick='ChangeDriver($num, \"" . SID . "\")' /></td></tr></table></div>"; $commandString = 'start /b Z:/usr/local/php5/php.exe Z:/home/sitrans.ru/www/php/test.php "888parampampam888"'; echo "<br />$commandString"; pclose(popen($commandString, 'r')); echo $SID1 . "|" . $result;// . "<br />$r1"; //ClearBlocking($SID1, $currenttime) //$commandString = "start /b Z:/usr/local/php5/php.exe Z:/home/sitrans.ru/www/php/clear.php '$SID1' '$currenttime'"; ?>
Я закоментил весь код во втором скрипте кроме вызова popen и все отработало, как надо. Вопрос теперь в том, какая часть кода заставляет выполняться скрипт с ожиданием?
Такие задачи решаются двумя способами. 1. Приоритет по сохранению. Никаких локов не делается, но при выдаче клиенту формы редактирования в ней сохраняется таймстамп последней редактирования этой записи. В некоторых случаях используют md5 содержимого. При сохранении данных, используя этот таймстамп или md5 - проверяют, что данные не изменились - и только тогда сохраняют их. Если данные изменились (кто-то уже отредактировал их) - клиенту выдается соответствующее сообщение, выводятся как новые данные из базы, так и поля с набранным им ранее - а дальше уже он решает, что делать. 2. Блокировка по началу редоктирования. В общем этот способ вы же и описали, только для чего вам эти все popen - не ясно. Вы ставите метку, кто редактирует, и время начала. Дается время жизни этой блокировки, о чем можно выдать клиенту сообщение... с обратным отсчетом. Теоретически, ему же, если много данных вводить, можно дать возможность продлять блокировку - ссылка, по нажатию на которую обновляется таймстамп начала блокировки. Второй клиент находит активную блокировку, выдает сообщение клиенту и, к примеру, сидит обновляется каждую минуту, проверяет - не пропала ли блокировка, не устарела ли она. На случай, если первый клиент попытается сохранить данные с устарелой блокировкой - можно применить комбинацию этих двух способов.
В общем вся проблема в невнимательности! Я указываю приличное время сна в файле clear.php и с дуру подключаю его через require_once - разумеется, основной поток ждет его выполнения! Убрал за ненадобностью лишнюю строчку кода и все заработало, как надо.