копирование файла

  • Автор темы Автор темы predator
  • Дата начала Дата начала

predator

web designer
копирование файла

есть старый zip файл и новый
старый иногда копируется системой в отдельную диру
новым надо заместить старый (это делает отдельный скрипт)
достаточно ли сделать copy
или надо делаеть flock в обоих скриптах?

если flock то как я понял в том скрипте который копирует старый файл надо делать LOCK_EX
а в скрипте который копирует новый поверх старого надо LOCK_SH

насчёт записи в файл я в курсе, а вот насчёт copy нигде внятного ответа не нашёл
 
PHP:
<?php
$file = 'example.txt';
$newfile = 'example.txt.bak';

if (!copy($file, $newfile)) {
    echo "не удалось скопировать $file...\n";
}
?>

Это взято из документации по PHP.
Не пойму, в чем проблема ?
 
Автор оригинала: ps2007 Не пойму, в чем проблема ?
проблема в том что я не уверен что будет ошибка при копировании
нового файла в то время как копируется старый

поэтому интересно мнение людей, которые сталкивались с похожей проблемой ;)
 
predator
Проблема в том что некоторые участники форума не умеют читать, а тем более вдумываться, в вопрос, им бы главнее бисер по метать.
 
1) Скопировать старый
2) Скопировать новый
В обоих случаях проверять результат выполнения функции copy()
 
ps2007
Не понимаешь в чем проблема, не пиши, договорились? Твой уровень знаний и умение читать, еще не того уровня, чтоб лезть другим помогать.
 
PHP:
$fh=fopen('filename','r');
if (!$fh)
{
  echo 'Error!';
} else {
  while (!flock($fh,$mode)) sleep(1);
  // обработка файла
  fclose($fh);
}
 
проверил, copy() кидает ошибку при попытке копирования нового файла в случае если старый файл копируется. но один из файлов получается битым

один скрипт:
PHP:
$i=0;
while($i<40) {
	if ( !copy( './services/old.zip', './services/old'.$i.'.zip' ) ) {
		p( 'test' );
	}
	$i++;
}

второй скрипт:
PHP:
$i=0; $_err=array();
while($i<20) {
	if ( !copy( './services/new.zip', './services/old.zip' ) ) {
		$_err[]=$i;
	}
	$i++;
}
p( $_err );

один из oldX.zip - битый

-~{}~ 04.02.10 16:42:

Автор оригинала: Sigorma
PHP:
$fh=fopen('filename','r');
во первых 2 разных скрипта
во вторых с какие $mode делать
в третьих не хочется чтобы тормозился первый скрипт (который копирует старый файл в другую диру)

-~{}~ 04.02.10 16:43:

в примере копируется в одну диру но смысл тот же
 
Не понимаешь в чем проблема, не пиши, договорились? Твой уровень знаний и умение читать, еще не того уровня, чтоб лезть другим помогать.
Ну так напиши ответ, если ты умеешь читать и понимаешь в чем проблема и дорос до того уровня, чтобы лезть другим помогать.
Умничать любой дурак сможет.
 
dimagolov поясни что ты имеешь ввиду - мне надо копировать файлы а не переименовывать

-~{}~ 04.02.10 17:39:

один скрипт:
PHP:
$i=0;
while($i<40) {
	$fp = fopen( './services/old.zip', "r");
	while (!flock($fp,LOCK_EX)) sleep(1);
	if ( !copy( './services/old.zip', './services/old'.$i.'.zip' ) ) {
		$_err[]=$i;
	}
	flock($fp, LOCK_UN);
	fclose($fp);
	$i++;
}
p( $_err );

второй скрипт:
PHP:
$i=0; $_err=array();
while($i<20) {
	$fp = fopen( './services/old.zip', "r");
	while (!flock($fp,LOCK_EX)) sleep(1);
	if ( !copy( './services/new.zip', './services/old.zip' ) ) {
		$_err[]=$i;
	}
	flock($fp, LOCK_UN);
	fclose($fp);
	$i++;
}
p( $_err );

только в этом случае обнуляется old.zip когда запускается второй скрипт...

-~{}~ 04.02.10 17:40:

есть подозрение что таким макаром flock не поиспользуешь ))
 
я про то, что операция copy - длительная и время выполнения зависит от размера файла. можно делать rename во временный файл, который копировать, а потом проверять, если за время копирования основной файл появился (его то не было, но он мог быть создад другим скриптом), то просто удаляем временный, если нет, то переименовываем обратно.
 
dimagolov неплохой вариант, только нужно учесть что копировать старый файл могут несколько клиентов поэтому надо проверять не создан ли новый и если создан то как то его лочить и опять возникают те же грабли

первый скрипт это т.с. эмуляция клиент-сервера а второй исключительно серверный скрипт который выполняется по крону

-~{}~ 04.02.10 18:10:

вобщем-то всё упирается в то чтобы файл заблокировать для записи но разрешить для чтения и проверить что файл блокирован

видел решение от stillwaiting:

Я бы сделал так: создал бы свою функцию mylock($f), myunlock($f) и islocked($f).

mylock($f) - лочит файл и создает в sys_get_temp_dir() файл "mysitename_lock15" с текущим time();
myunlock($f) - разлочивает файл и удаляет этот файл;
ismylocked() - пытается прочитать содержимое файла "mysitename_lock15" и, если разница времени, которое он хранит, с текущим time() меньше TIMEOUT значения, то возвращает true, иначе false;

Также можно ввести функцию mylocktouch(), которая обновляет значение в файле... это на случай если скрипт лочит файл надолго.

но хочется решение попроще, нативное т.с. ))
взял отсюда http://phpclub.ru/talk/showthread.php?threadid=116766
 
только нужно учесть что копировать старый файл могут несколько клиентов
я не знаю кто почему и зачем там хочет у тебя копировать, но если вместо копирования ты ВСЕГДА будешь использовать последовательность
1. перемеиновали в уникальный временный файл
2. скопировали во 2-й временный файл.
3. если смогли, то переименовали в нужный, возможно удалив старую версию. и опять таки, ее можно не удалять, а переименовывавть, а удалять после успешного переименования того, что скопировали.
4. вернули 1-й временный файл на место исходного, если это возможно.

при этом именно длительная по времени операция копирования у тебя будет из одного уникального файла в другой, а с разделяемыми файлами будут очень быстрые операции переименования, вероятность возникновение коллизий при этом будет минимальна.
 
ps2007
Я не обязан никому помогать. Это понятно? Так, что давай ты просто прислушаешься к моему совету.
 
dimagolov я понял твою схему но смотри
если допустим мы переименовали в уникальный файл и начали копировать. а в это время другой процесс тоже хочет скопировать файл, а его там нет - он переименован...

такое возможно, хотя и очень редко

-~{}~ 05.02.10 13:04:

получается надо делать цикл ожидания
что замедлит работу
копирование будет не параллельным а последовательным

-~{}~ 05.02.10 14:01:

вот тут грамотная статья про flock
http://omsk777.ru/flock.html
вывод - лучше использовать базы данных при большом трафике на Вашем сайте.
я про это тоже думал но пока воспользуюсь решением от stillwaiting
вот пример реализации от моих ребят : )

один скрипт:
PHP:
set_time_limit(0);

$i=0; 
$_err=array();
while($i<300) {
 
 while(file_exists('./test/user')) {
  echo $j++;
  sleep(1);
 }
 $f=fopen('./test/system','a');

 if ( !copy( './test/new.zip', './test/old.zip' ) ) {
        $_err[]=$i;
    }

    fclose($f);
    unlink('./test/system');
    $i++;
}
print_r( $_err );

второй скрипт:
PHP:
set_time_limit(0);

$i=0;
while($i<300) {
 while (file_exists('./test/system')) {
  echo $j++;
  sleep(1);
 }
 $f = fopen('./test/user','a');
    if ( !copy( './test/old.zip', './test/old'.$i.'.zip' ) ) {
      print( 'test' ); 
    }
    fclose($f);
    unlink('./test/user');
    
    $i++;
}
 
dimagolov ага - в место где собирается пакет из разных файлов, не буду углубляться в детали
 
то есть у тебя в одно и то же время файл может переписываться другим и при этом копироваться одновременно в несколько разных мест? тебе не кажется, что в архитектуре что-то нужно менять?

если архитектура именно такая, то тебе нужно ждать с копированием "в" пока происходит копирование "из". чтобы не ждать когда появится оригинал при копировании "из", нужно копирование "в" делать через переименование. а проверять идет или нет копирование "из" можно и через отдельные файлы-семафоры, создаваемые при копировании "из" и удаляемые при окончании. только при этом падение скрипта во время копирования может привести к бесконечной блокировке, но и это можно обойти контролем времени начала блокировки и лимитом на нее.
 
архитектура нормальна если учесть что
new.zip - это последняя версия wordpress
old.zip - предыдущая
а пользователи устанавливают на своих серверах wp + могут его заранее настроить под себя.

поэтому old.zip может копироваться одновременно несколькими процессами а new.zip иногда в это вклинивается

скрипты которые я привёл - тестовые, они показывают что решение рабочее, конкретная реализация ессно может сильно отличатся.

спасибо всем за помощь : ))
 
Сверху