2012-01-05 61 views
0

我正在構建一個數據庫,其中包含有關網絡上主機的信息。我將這些數據顯示在由PHPMaker生成的網站上。 (http://www.hkvstore.com/phpmaker/)編輯nmap2db.pl(更改數據庫更新語句)

該項目的目的是建立一個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表,而不是隻覆蓋每次。 我已經做了一些細微修改腳本(移除了DB模式的某些字段)

引擎收錄完整的腳本: http://pastebin.com/V3AwcBVR

它看起來像線92〜95是神奇在哪裏發生。

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

所以無論如何......我不知道Perl,我也不擅長SQL。是否清楚我想要達到什麼目的?是否可以編輯這個腳本來做我想要的?

回答

1

這看起來很簡單。

但是,現在數據庫的結構方式是,主鍵是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地址在統計學上是獨一無二的,所以你不應該得到重複。如果您擁有一個聲稱擁有多個IP地址的mac地址,則無論如何您都可能想知道這一點。

從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

我明白你在說什麼,但我喜歡我的方式更好:)這裏的原因:MAC地址不能是主要的,因爲不會永遠是一個...但主要是我沒有好的方法來顯示整個IP範圍的數據....也許我可以寫一個匹配的ip範圍的選擇語句,並找到最新的記錄。嗯。我會考慮一下,並與我的DBA傢伙討論這個計劃。我喜歡有選擇,我仍然想找到一種方法來完成我最初的要求。 – AaronJAnderson 2012-01-05 22:21:29

+0

啊,我明白你現在說的話。不知何故,我錯過了你想要一張單獨的桌子。 – AWT 2012-01-06 18:15:49

+0

然後我會在腳本的第98行創建另一個函數,正好在$ np-> callback(\&insert_host)之上;並調用一個名爲insert_historic的新函數。 – AWT 2012-01-06 18:16:56

0

或者,用「歷史表」主題:

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變量,你可以調用insert_historic子,並將所有這些值保存到IPHistoric表中。

下面的代碼不會獨立運行,因爲它依賴於您鏈接的代碼中設置的許多其他事情。但是,您應該能夠複製/插入$ {INSERT_HOSTORIC}部分的$ {INSERT_HOST}部分下方,並且insert_historic子部分將在您的insert_host子部分的正下方。

祝你好運!

0

我們添加了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 }