редактирование nmap2db.pl (изменение операторов обновления базы данных) - PullRequest
0 голосов
/ 05 января 2012

Я создаю базу данных, которая содержит информацию о хостах в моей сети.Я представляю эти данные на сайте, созданном PHPMaker.(http://www.hkvstore.com/phpmaker/)

Целью этого проекта является создание системы управления IP-адресами.

Важно сохранить исторические данные любой записи в БД. Если мы вручную изменимЗаписать на сайт, построенный PHPMaker, мы можем записать старые данные записи в другую таблицу. Код, используемый для этого, выглядит следующим образом. (Может быть, это не совсем актуально, но я привел это здесь, чтобы вы могли понять, как выглядят данныенапример)

$sInsertSql = "INSERT INTO IPHistoric (ip, status, hostname, last_scanned, mac, ManualHost, Reservation) 
    VALUES ('" . $rsold['ip'] . "', '" . $rsold['status'] . "', '" . $rsold['hostname'] . "', '" . $rsold['last_scanned'] . "', '" . $rsold['mac'] . "', '" . $rsold['ManualHost'] . "', '". $rsold['Reservation'] . "')";

Теперь я также заполняю данные скриптом perl с именем nmap2db.pl (http://search.cpan.org/~apersaud/Nmap-Parser-1.2/tools/nmap2db.pl), который позволяет очень легко выполнить сканирование nmap подсети и заполнить ееданные в таблицу.

Что мне нужно:

Мне нужен скрипт perl для сохранения любых старых данных в таблицу IPHistoric вместо простой перезаписи каждый раз. Я сделал несколько небольших изменений в скрипте(удалены некоторые поля из схемы БД)

Вставить полный скрипт: http://pastebin.com/V3AwcBVR

Похоже, что строки с 92 по 95 - это место, где происходит магия.

$S{INSERT_HOST}
    = qq{REPLACE INTO }
    . $G{TABLE}
    . qq{ (ip, mac, status, hostname) VALUES (?,?,?,?)};

Так или иначе ... Я не знаю Perl, и я не очень хорош в SQL.Понятно, что я пытаюсь достичь?Можно ли отредактировать этот скрипт, чтобы делать то, что я хочу?

Ответы [ 3 ]

1 голос
/ 05 января 2012

Это выглядит довольно просто.

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

#Schema for table, simple for now
$S{CREATE_TABLE} = qq{  CREATE TABLE } . $G{TABLE} . qq{ (
  ip              VARCHAR(15) PRIMARY KEY NOT NULL,
  mac             VARCHAR(17) ,
  status          VARCHAR(7) DEFAULT 'Down',
  hostname        VARCHAR(50),
  last_scanned    TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
  };

Эта схема разрешает только одну запись для каждого IP-адреса, что означает, что если вы обновите существующую запись новыми данными, старые данные будут отброшены.

Вы можете предотвратить это, удалив ограничение первичного ключа из схемы таблицы для IP-адреса и вместо этого поместив его, скажем, в MAC-адрес. Поскольку MAC-адреса статистически уникальны, вы никогда не должны получать дубликаты. Если у вас есть один mac-адрес, претендующий на владение несколькими IP-адресами, вы все равно можете узнать об этом.

С удалением ограничения первичного ключа из столбца ip теперь можно иметь несколько записей для одного и того же IP-адреса. Хитрость заключается в том, чтобы выяснить, какой из них является текущим. Вы можете сделать это с отметками времени. Создайте два дополнительных столбца в вашей базе данных и назовите их как CREATE_TIME и END_TIME.

Каждый раз, когда запись вставляется в базу данных, вставьте текущую метку времени в CREATE_TIME. Если запись для этого ip уже существует, вставьте текущую метку времени в END_TIME, а затем создайте новую запись. Таким образом, вы будете знать, как долго каждая IP-запись была назначена на основе временных меток CREATE_TIME и END_TIME.

Поскольку END_TIME записывается только при изменении записи, вы можете получить текущий набор записей IP, выполнив что-то вроде:

    select * from TABLE where END_TIME is NULL;

Надеюсь, это имело смысл.

0 голосов
/ 07 января 2012

мы добавили часть INSERT_HISTORY.

$S{INSERT_HISTORY}
=   qq{ INSERT_INTO IPHistoric }
    . qq{ ip, status, hostname, last_scanned, mac, ManualHost, Reservation }
  . qq { SELECT ip, status, hostname, last_scanned, mac, ManualHost, Reservation FROM }
    . $G{TABLE}
    . qq { WHERE ip = ? AND ( mac <> ? OR hostname <> ? ) };

$S{UPDATE_HOST}
= qq{UPDATE }
  . $G{TABLE}
  . qq { SET mac = ? , status = ?, hostname = ?, last_scanned = CURRENT_TIMESTAMP }
0 голосов
/ 06 января 2012

Альтернативно, используя тему "историческая таблица":

use vars qw(%S %G %H);

$H{TABLE} ||='IPHistoric';

$S{INSERT_HISTORIC}
    = qq{INSERT INTO }
    . $H{TABLE}
    . qq{ (ip, status, hostname, last_scanned, mac, ManualHost, Reservation) VALUES (?,?,?,?,?,?,?)};

my $hist_ins = eval { $dbh->prepare_cached( $S{INSERT_HISTORIC} ) };
my $np = new Nmap::Parser;
$np->callback( \&insert_historic );

sub insert_historic {
    my $host = shift;
    my $os   = $host->os_sig();

    #ip, mac, status, hostname
    my @input_values = (
        $host->rsold['ip'],
        $host->rsold['status'],
        $host->rsold['hostname'],
        $host->rsold['last_scanned'],
        $host->rsold['mac'],
        $host->rsold['ManualHost'],
        $host->rsold['Reservation']
    );

    my $rv
        = $hist_ins->execute(@input_values) ? "ok" : "OOPS! - " . DBI->errstr;

    printf( "\t..> %-15s : (%4s) : %-s\n", $host->addr, $host->status, $rv );
}

Возможно, в нем есть несколько опечаток, но вы поняли идею. Как правило, как только вы установите переменные $ rsold, вы можете вызвать sub_historic sub и сохранить все эти значения в таблице IPHistoric.

Приведенный ниже код не будет работать автономно, поскольку он опирается на множество других вещей, установленных в связанном коде. Но вы должны быть в состоянии скопировать / поместить раздел $ S {INSERT_HISTORIC} прямо под разделом $ {INSERT_HOST}, и сабвуфер insert_historic окажется прямо под сабвуфером insert_host.

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...