Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Однопользовательская работа скрипта 
:(
    Опции темы
sneJok
Дата 27.10.2010, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 1.10.2007

Репутация: нет
Всего: нет



Добрый день. Такая задачка:
при выполнении скрипта, не допустить повторную его работу, пока первый пользователь не закончит работу со скриптом.

На пальцах:
1 пользователь начал работу со скриптом, 2 пользователь в это время обращаясь к скрипту получит какое-либо сообщение о занятости.

Вот сам код

Код

<?
$filename='test.txt';
$file=fopen($filename,"r") or die ("Файл не найден");
if (flock($file,2)) {
 echo 'Work';
  sleep(5);
} else {echo 'Not Work';}
@flock($file, 3);
fclose($file);
?>


В чем может быть ошибка? Всегда выводится Work.
PM MAIL   Вверх
skyboy
Дата 27.10.2010, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 75
Всего: 260



с работой flock не знаком, специфики не знаю.
но соображения имеются.
не значит ли использование flock "заблокировать файл и оставить доступ только текущему процессу"? если означает, то у тебя ж все запросы к РНР файлам идут в рамках одного процесса, верно? попробуй увеличить паузу в скрипте и открыть заблокированный файл параллельно при помощи другого процесса. скажем, блокнота. у меня вот файл блокнотом открывается только на чтение во время работы РНР скрипта.

Добавлено через 54 секунды
кроме того, в первом же комментарии на php.net/flock вижу следующее:
Цитата

1) flock() is not safe if multiple php sessions are simultaneously locking.
2) fopen( , 'a') is not safe if multiple php sessions are simultaneously appending.
3) usleep and sleep are known for having problems.

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

Добавлено через 3 минуты и 5 секунд
может, семафоры использовать?
PM MAIL   Вверх
sneJok
Дата 27.10.2010, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 1.10.2007

Репутация: нет
Всего: нет



skyboy, благодарю за быстроту и идеи. Видимо по поводу одного процесса вы правы.
По поводу семафоров - надо разбираться, буду гуглить.
Есть еще идейки?
PM MAIL   Вверх
sneJok
Дата 27.10.2010, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 1.10.2007

Репутация: нет
Всего: нет



Начал смотреть простейший пример из одной статьи:

Код

<?
$MEMSIZE = 512; //  объём выделяемой разделяемой памяти
$SEMKEY = 1;   //  ключ семафора
$SHMKEY = 2;   //  ключ разделяемой памяти

echo "Старт.\n";

// Создаем семафор
$sem_id = sem_get($SEMKEY, 1);
if ($sem_id === false)
{
    echo "Ошибка при создании семафора";
    exit;
}
else
    echo "Создан семафор $sem_id.\n";

// Занимаем семафор
if (! sem_acquire($sem_id))
{
    echo "Ошибка при попытке занять семафор $sem_id.\n";
    sem_remove($sem_id);
    exit;
}
else
    echo "Успешно занят семафор $sem_id.\n";

// Подключаем разделяемую память
$shm_id = shm_attach($SHMKEY, $MEMSIZE);
if ($shm_id === false)
{
    echo "Ошибка при подключении разделяемой памяти.\n";
    sem_remove($sem_id);
    exit;
}
else
    echo "Успешное подключение разделяемой памяти: $shm_id.\n";

// Пишем переменную 1
if (!shm_put_var($shm_id, 1, "Переменная 1"))
{
    echo "Ошибка при попытке записать переменную 1 в разделяемую память $shm_id.\n";

    // Овобождаем ресурсы.
    sem_remove($sem_id);
    shm_remove($shm_id);
    exit;
}
else
    echo "Переменная 1 записана в разделяемую память.\n";

// Пишем переменную 2
if (!shm_put_var($shm_id, 2, "Переменная 2"))
{
    echo "Ошибка при попытке записать переменную 2 в разделяемую память $shm_id.\n";

    // Освобождаем ресурсы.
    sem_remove($sem_id);
    shm_remove ($shm_id);
    exit;
}
else
    echo "Переменная 2 записана в разделяемую память.\n";

// Читаем переменную 1
$var1 = shm_get_var($shm_id, 1);
if ($var1 === false)
{
    echo "Ошибка при попытке прочитать переменную 1 из разделяемой памяти $shm_id, " .
         "возвращенное значение=$var1.\n";
}
else
    echo "Прочитана переменная 1=$var1.\n";

// Читаем переменную 2
$var2 = shm_get_var ($shm_id, 2);
if ($var1 === false)
{
     echo "Ошибка при попытке прочитать переменную 2 из разделяемой памяти $shm_id, " .
          "возвращенное значение=$var2.\n";
}
else
    echo "Прочитана переменная 2=$var2.\n";

// Освобождаем семафор
if (!sem_release($sem_id))
    echo "Ошибка при попытке освободить семафор $sem_id.\n";
else
    echo "Семафор $sem_id освобожден.\n";

// Удаляем сегмент разделяемой памяти
if (shm_remove ($shm_id))
    echo "Сегмент разделяемой памяти успешно удален.\n";
else
    echo "Ошибка при попытке удалить сегмент разделяемой памяти $shm_id.\n";

// Удаляем семафор.
if (sem_remove($sem_id))
    echo "Семафор успешно удален.\n";
else
    echo "Ошибка при попытке удалить семафор $sem_id.\n";

echo "Конец.\n";

?>


На выделенной строке ошибка типа - Call to undefined function: sem_get()
PM MAIL   Вверх
skyboy
Дата 27.10.2010, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 75
Всего: 260



видимо, от того, что по умолчанию эти функции не активированы :(
PM MAIL   Вверх
sneJok
Дата 28.10.2010, 00:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 1.10.2007

Репутация: нет
Всего: нет



Чтобы еще придумать.
PM MAIL   Вверх
skyboy
Дата 28.10.2010, 08:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 75
Всего: 260



проверять не блокировку файла, а его наличие.
соответственно, скрипт в начале работы файл создает, а в конце работы удаляет.
PM MAIL   Вверх
MoLeX
Дата 28.10.2010, 09:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Местный пингвин
****


Профиль
Группа: Модератор
Сообщений: 4076
Регистрация: 17.5.2007

Репутация: 46
Всего: 140



в flock попробуйте в качестве второго параметра указывать LOCK_EX | LOCK_NB
Код

$filename='test.txt';
$file=fopen($filename,"r") or die ("Файл не найден");
if (flock($file, LOCK_EX | LOCK_NB)) {
 echo 'Work';
  sleep(5);
flock ($file, LOCK_UN);
} else {echo 'Not Work';}
fclose($file);



--------------------
Amazing  smile 
PM MAIL WWW ICQ   Вверх
BuShaRt
Дата 28.10.2010, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1391
Регистрация: 29.6.2006

Репутация: 4
Всего: 6



Я предлагаю вынести вопрос с уровня "работа с файлом" на уровень "работа с процессом" и просто за счет дополнительного функционала проверять не ту ли метки (полагаю в БД) о том, что ведется работа с процессом. Метка снимается по условию:
1. Пользователь обратился к другому процессу
2. Пользователь нажал кнопку окончания работы с этим процессом
3. Пользователь N-ое время бездействовал.

По минимуму пользователей можно идентифицировать по IP, но лучше сделать авторизацию.

Это сообщение отредактировал(а) BuShaRt - 28.10.2010, 15:07
PM MAIL   Вверх
sneJok
Дата 28.10.2010, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 1.10.2007

Репутация: нет
Всего: нет



skyboy, хорошее решение. но вот постоянно удалять\создавать файл...

MoLeX, прямо в ТОЧКУ. Работает. Жаль, что не могу поднять вам репутацию. Огромное спасибо!


BuShaRt, как перспектива - это да, но пока нет даже базы как таковой. А айпишников - огромное количество крутится.

Огромное Вам спасибо! 

Это сообщение отредактировал(а) sneJok - 28.10.2010, 23:02
PM MAIL   Вверх
ksnk
Дата 28.10.2010, 23:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



У skyboy, решение более устойчиво к внезапному падению исполняющего работу скрипта. После падения остается файл, у которого можно проверить время создания. Если оно достаточно велико - процесс грохнулся, и его можно еще раз стартовать. При блокировке такой информации не остается. Хотя можно время файла обновлять touch'ем. Хотя если совместить touch с блокировкой - может получится заодно и время последнего исполнения процесса.
Метка в базе данных немного сложное решение - нужно писать больше букв ;) 

Есть еще всякие  Memcache/ тоже можно использовать для семафоров, но как и с семафорами - не в каждом сервере оно есть...

Это сообщение отредактировал(а) ksnk - 28.10.2010, 23:25


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
sneJok
Дата 14.11.2010, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 1.10.2007

Репутация: нет
Всего: нет



Возвращаюсь опять к теме.
Немного изменена задача: С помощью чего еще можно сделать работу скрипта только для одного пользователя, при этом второму и последующим просто выдавать сообщение о занятости. Место имеет также обращение до 5 одновременных (!) обращений к скрипту и собственно как дать только 1 обращенному отработать?

Реализация с lock не работает, иногда еще одно одновременное подключение проскакивает.

Сделал через файл:
Код

<?
if(file_exists('111.txt')) {echo 'Blocked';} else {
$h = fopen("111.txt","w"); fclose($h);
$filename='dbtime.txt';
$file=fopen($filename,"r+") or die ("Файл не найден");

// Здесь выполняются операции с файлом dbtime.txt чтение+запись

fclose($file);
sleep(1);
unlink("111.txt");
}
?>


Тоже интересная ситуация. При увеличении sleep скрипт более менее стабильнее работает, но все равно пропускает двух пользователей. Самое интересное, если не использовать sleep, скрипт вообще не работает :/. Совсем непонятная логика.

Это сообщение отредактировал(а) sneJok - 14.11.2010, 14:34
PM MAIL   Вверх
ksnk
Дата 14.11.2010, 14:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Цитата(sneJok @  14.11.2010,  14:27 Найти цитируемый пост)
Реализация с lock не работает, иногда еще одно одновременное подключение проскакивает.

А пример из мана точно не работает?

Example 611. flock() example
Код

$fp = fopen("/tmp/lock.txt", "w+");

if (flock($fp, LOCK_EX)) { // do an exclusive lock
   fwrite($fp, "Write something here\n");
   flock($fp, LOCK_UN); // release the lock
} else {
   echo "Couldn't lock the file !";
}

fclose($fp);





--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
sneJok
Дата 14.11.2010, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 1.10.2007

Репутация: нет
Всего: нет



ksnk, к сожалению, нет. При одновременном обращении - проходит > 1 пользователей.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0573 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.