Перед тем как перейти к следующему способу преобразования IP-адресов в имена, хотелось бы добавить к процессу создания файла узлов еще одну хитрую возможность обработки, поскольку один-единственный файл приобретает общесетевое значение. Ошибка в этом файле повлияет на всю сеть. Чтобы обезопасить себя, нужен способ, выполняющий откат изменений, нарушивших файл. Особенно необходимо иметь возможность вернуться назад к предыдущим версиям файла.
Самый элегантный способ создать подобную машину времени - добавить к процессу систему контроля исходного кода. Такой контроль используется разработчиками с целью:
Подобные средства контроля очень полезны для системного администратора. Проверка ошибок, добавленная в разделе «Проверка ошибок в процессе генерирования файла узлов», поможет справиться лишь с некоторыми опечатками и синтаксическими ошибками, но не спасет от семантических ошибок (таких как удаление важного имени узла, присвоение ошибочного IP-адреса, ошибка в имени узла). В процесс преобразования можно добавить проверку и семантических ошибок, но отловить все возможные погрешности все равно не удастся. Мы уже говорили, что защиты от дураков не существует, потому что они изобретательны.
Можно, наверное, предположить, что было бы лучше применить систему контроля исходного кода к процессу редактирования первоначальной базы данных, но есть две веские причины, по которым очень важно применить ее к данным, получаемым в результате:
Время
Для большого набора данных процесс преобразования может занять некоторое время. Если ваша сеть «упала», и вам необходимо вернуться к предыдущей версии, то необходимость наблюдать, пока Perl сгенерирует нужный файл, вас просто обескуражит (и все это при условии, что вы смогли сразу добраться до Perl).
База данных
Если для хранения данных вы будете использовать настоящую базу данных (а часто это правильный выбор), то может просто не существовать способа применить к ней систему контроля версий. Вероятно, вам придется писать собственные механизмы контроля версий для процесса редактирования базы данных.
В качестве системы контроля исходного кода я выбрал систему контроля версий RCS. У RCS есть несколько возможностей, дружественных к Perl и системному администрированию:
Если вы никогда не работали с RCS, загляните сначала в приложение А. Впредь будем считать, что вы знакомы с основным набором команд RCS.
Крэйг Фретер (Craig Freter) написал объектно-ориентированный модуль Res, который упрощает применение RCS из Perl. Для этого необходимо:
Добавим модуль Res в программу генерации файла узлов, чтобы увидеть, как он работает, и применим другой способ вывода данных. Теперь они будут записываться в определенный файл, а не в стандартный поток вывода STDOUT, как было раньше. Ниже приведен только измененный код. Пропущенные строки, представленные в виде «...», можно найти в предыдущем примере:
$outputfile="hosts.$$";
# временный файл для вывода
$target="hosts";
# где сохранить преобразованные данные
open(OUTPUT,"> Soutputfile") or die
"Невозможно записать в файл
$outputfile:$!\n";
print OUTPUT "»\n\# host file - GENERATED BY $0\n
tt DO NOT EDIT BY HAND! \nft\n"; print OUTPUT "
Converted by $user on ".scalar(localtime)."\nfl\n";
foreach my $dept (keys %depts) {
print OUTPUT "tt number of hosts in the $dept department:
$depts{$dept}.\n"; }
print OUTPUT "tt total number of hosts: ".scalar(keys %entries)."\ne\n\n";
обходим в цикле все узлы и выводим комментарий tt вместе с самой записью
foreach my Sentry (sort byaddress keys %entries) { print OUTPUT
"# Owned by ",$entries{$entry}->{owner},"
(", $entries{$entry}->{department},"): ",
$entries{$entry}->{building},"/".
Sentries{$entry}->{room},"\n";
print OUTPUT
$entries{$entry}->{address},"\t", $entries{$entry}->{name},"
", Sentries{$entry}->{aliases},"\n\n"; }
Close(OUTPUT);
use Res;
путь к RCS
Rcs->bindir(Vusr/local/bin1);
создаем новый RCS-объект
my $rcsobj = Rcs->new;
ft передаем ему имя получаемого файла
$rcsobj->file($target);
tt получаем его из репозитория RCS (он уже должен быть там)
$rcsobj->co('-!');
ft переименовываем вновь созданный файл
rename($outputfile,$target) or
die "Невозможно переименовать Soutputfile в $target:$!\n";
помещаем его в репозиторий RCS
$rcsobj->ci("-u","-m"."Converted by $user on ".scalar(localtime));
В данном примере предполагалось, что целевой файл хотя бы один раз помещался в репозиторий.
Взглянув на фрагмент записей из rlog hosts, можно понять, как действует программа:
revision 1.5
date: 1998/05/19 23:34:16; author: dnb; state: Exp; lines: +1 -1
Converted by David N. Blank-Edelman (dnb) on Tue May 19 19:34:16 1998
revision 1.4
date: 1998/05/19 23:34:05; author: eviltwin; state: Exp; lines: +1 -1
Converted by Divad Knalb-Namlede (eviltwin) on Tue May 19 19:34:05 1998
revision 1.3
date: 1998/05/19 23:33:35; author: dnb; state: Exp; lines: +20 -0
Converted by David N. Blank-Edelman (dnb) on Tue May 19 19:33:16 1998
Из предыдущего примера видно, что между версиями файла нет больших различий (обратите внимание на часть, включающую lines:), зато отслеживаются все изменения, происходящие при создании файла. При необходимости узнать, что именно произошло, достаточно воспользоваться командой rcsdiff. В крайнем случае, всегда можно вернуться к предыдущим версиям, если какие-либо изменения приведут сеть в неработоспособное состояние.