Как не крути, а в новогодние праздники, риск порчи файлов значительно возрастает. Не миновала сия беда и меня. Как не трудно догадаться, я перепутал диск при форматировании и… да-да, все что было нажито неправедным путем непосильным трудом, в один момент было уничтожено.
Помянув сборник софта и архив отсканированных справочников, я задумался над вопросом бекапов. И… Пришел к выводу, что того что мне в самом деле требуется, нет. Точнее конечно же есть, но либо стоит дорого, либо работает не так, как мне бы того хотелось.
Закончив с пытками гугла на тему: «сделай мне хорошо», решил поступить как истинный 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