Как не крути, а в новогодние праздники, риск порчи файлов значительно возрастает. Не миновала сия беда и меня. Как не трудно догадаться, я перепутал диск при форматировании и… да-да, все что было нажито неправедным путем непосильным трудом, в один момент было уничтожено.
Помянув сборник софта и архив отсканированных справочников, я задумался над вопросом бекапов. И… Пришел к выводу, что того что мне в самом деле требуется, нет. Точнее конечно же есть, но либо стоит дорого, либо работает не так, как мне бы того хотелось.
Закончив с пытками гугла на тему: «сделай мне хорошо», решил поступить как истинный Unix`оид, хоть и работающий в форточках. А именно: не выпендривайся, чем проще — лучше.
Тут я вспомнил презентацию MacOS на которой демонстрировали их Time Machine. Ведь если подумать, очень удобно иметь возможность получить доступ к любому файлу за любой день. Но… Если делать полные копии в виде архивов, то никаких объемов не хватит, чтобы это все хранить. Дальше мысль зацепилась за инкрементные бекапы. То есть в первый раз вы делаете полный архив, а затем архивируете только то, что изменилось.
И… Этот вариант я тоже отбросил, как не удобный для моего случая. Во-первых, существует необходимость в возможности удалять произвольные «дни». А во-вторых, я очень часто переименовываю свои файлы и время от времени перекладываю из директорию в директорию. А это, в свою очередь, к моему удивлению, срезало почти всех кандидатов в «бекаперы». То есть, софт тупо смотрел на имя файла, дату его изменения и… и все. В итоге бекап разбухал.
Итак, спасли меня две идеи:
Во-первых, не важно как называется файл, важно содержание. Таким образом с каждого файла должно сниматься несколько хешей и на основе этой сигнатуры можно достаточно точно судить, что это за файл. В моем случае я ограничился снятием md5 суммы и размером файла. Выбор конечно спорный, но для сканов этого вполне достаточно.
Во-вторых, если файл не изменился или изменилость только его имя, надо копировать не весь файл, а делать на него жесткую ссылку, благо в NTFS такие есть.
Если кто не знает, то благодаря команде:
В windows можно получить настоящую жесткую ссылку.
В итоге, получился простой алгоритм, который я, не заморачиваясь, оформил на консольном PHP. Теперь бекап происходит при подключении переносного диска к компьютеру, либо (если диск уже подключен) раз в сутки.
И вот собственно сам «бекапер».
Его конфигурация:
Ну и BAT`ник его запускающий:
Помянув сборник софта и архив отсканированных справочников, я задумался над вопросом бекапов. И… Пришел к выводу, что того что мне в самом деле требуется, нет. Точнее конечно же есть, но либо стоит дорого, либо работает не так, как мне бы того хотелось.
Закончив с пытками гугла на тему: «сделай мне хорошо», решил поступить как истинный Unix`оид, хоть и работающий в форточках. А именно: не выпендривайся, чем проще — лучше.
Тут я вспомнил презентацию MacOS на которой демонстрировали их Time Machine. Ведь если подумать, очень удобно иметь возможность получить доступ к любому файлу за любой день. Но… Если делать полные копии в виде архивов, то никаких объемов не хватит, чтобы это все хранить. Дальше мысль зацепилась за инкрементные бекапы. То есть в первый раз вы делаете полный архив, а затем архивируете только то, что изменилось.
И… Этот вариант я тоже отбросил, как не удобный для моего случая. Во-первых, существует необходимость в возможности удалять произвольные «дни». А во-вторых, я очень часто переименовываю свои файлы и время от времени перекладываю из директорию в директорию. А это, в свою очередь, к моему удивлению, срезало почти всех кандидатов в «бекаперы». То есть, софт тупо смотрел на имя файла, дату его изменения и… и все. В итоге бекап разбухал.
Итак, спасли меня две идеи:
Во-первых, не важно как называется файл, важно содержание. Таким образом с каждого файла должно сниматься несколько хешей и на основе этой сигнатуры можно достаточно точно судить, что это за файл. В моем случае я ограничился снятием md5 суммы и размером файла. Выбор конечно спорный, но для сканов этого вполне достаточно.
Во-вторых, если файл не изменился или изменилость только его имя, надо копировать не весь файл, а делать на него жесткую ссылку, благо в NTFS такие есть.
Если кто не знает, то благодаря команде:
fsutil hardlink create <ссылка> <файл>В windows можно получить настоящую жесткую ссылку.
В итоге, получился простой алгоритм, который я, не заморачиваясь, оформил на консольном PHP. Теперь бекап происходит при подключении переносного диска к компьютеру, либо (если диск уже подключен) раз в сутки.
И вот собственно сам «бекапер».
<?php // $dir = array(); $hah = array(); $hah_new = array(); $file = array(); $copy = 0; $link = 0; include 'conf.php'; $date = date('Y-m-d'); // выход если бекап на сегодня уже существует if(is_dir($date)){ exit("Backup already exists\n"); } // составляем список существующих файлов foreach(glob('*', GLOB_ONLYDIR) as $v){ if(is_file($v.'/hah.db')){ $hah = array_merge($hah, unserialize(file_get_contents($v.'/hah.db'))); } } // создаем дерево директорий foreach($dir as $v){ $x = explode('/', $v); array_unshift($x, $date); $x[1] = substr($x[1], 0, 1); foreach($x as $k=>$v){ $y = implode('/', array_slice($x, 0, $k+1)); if(!is_dir($y)){ mkdir($y); } } } // получаем список файлов while($n = array_pop($dir)){ if(!is_dir($date.'/'.substr($n, 0, 1).'/'.substr($n, 3))){ mkdir($date.'/'.substr($n, 0, 1).'/'.substr($n, 3)); } $dir = array_merge($dir, glob($n.'/*', GLOB_ONLYDIR)); $file = array_merge($file, array_diff(glob($n.'/*'), glob($n.'/*', GLOB_ONLYDIR))); } // копируем новые и линкуем старые файлы foreach($file as $k=>$v){ $x = md5_file($v).filesize($v); if(!$x){ continue; } $f = $date.'/'.substr($v, 0, 1).'/'.substr($v, 3); if($hah[$x]){ exec('fsutil hardlink create "'.$f.'" "'.$hah[$x].'"'); $hah_new[$x] = $f; $link++; }else{ copy($v, $f); $hah_new[$x] = $f; $copy++; } print ceil($k*100/count($file))."%\r"; } print "\nLink: ".$link."\n"; print "Copy: ".$copy."\n"; // сохраняем информацию о файлах file_put_contents($date.'/hah.db', serialize($hah_new)); exit;
Его конфигурация:
<?php date_default_timezone_set('Asia/Novosibirsk'); $dir[] = 'c:/scan'; // сканы $dir[] = 'c:/web'; // корень локального сервера $dir[] = 'c:/gohsrf'; // приказы $dir[] = 'q:'; // флешка
Ну и BAT`ник его запускающий:
@echo off cls php backup.php pause
