2016-02-16 91 views
1

我是新來的Perl和實踐我正在寫一個簡單的Perl腳本來檢查我的家庭網絡的可用IP地址,並檢查他們的MAC地址,供應商和打開端口爲他們每個人。 所有我想放在mysql數據庫中的信息。 這裏是我的代碼:用於檢查網絡的Perl腳本

#!/usr/local/bin/perl 
use strict; 
use warnings; 
use Net::Ping; 
use Net::ARP; 
use DBI; 
use IO::Socket::PortState qw(check_ports); 
require config; 
my $proto = 'tcp'; 
my @ports = (21,22,23,80,8080); 
my $address; 
my $ping_timeout = 1; 
my $host; 
for my $i (18..21) 
{ 
     $host = "10.20.1.$i"; 
     my $timeout = 1; 
     my $pinger = Net::Ping->new('icmp', $timeout); 
     print "$host "; 
     if ($pinger->ping($host)) 
     { 
       my $mac = Net::ARP::arp_lookup("em0","$host"); 
       my $vendor = vendor_lookup($mac); 
       $vendor=~ s/^\s+|\s+$//g; 
       print "$mac $vendor "; 
       foreach my $port (@ports) 
       { 
         my($section, $ping_timeout, %porthash); 
         $porthash{$proto}{$port}{'name'} = $section; 
         check_ports($host, $ping_timeout, \%porthash); 
         my $open = $porthash{$proto}{$port}{'open'}; 
         if ($open) { 
           print "$port "; 
         } 
       } 
       print "\n"; 
     } 
} 

如果我運行該腳本,我會收到類似的東西:

10.20.1.18 38:ea:a7:6f:d9:05 Hewlett Packard 80 8080 
10.20.1.19 fc:15:b4:31:77:76 Hewlett Packard 80 8080 
10.20.1.20 e8:39:35:25:dd:36 Hewlett Packard 22 80 

我的問題是,我似乎還沒有找到一個答案如何,所有這些都那信息($ host,$ mac,$ vendor,$ port)並將其放入數據庫,因此如果我們將$ port變量放在@array中,它將與其他數組具有不同的大小。

我的數據庫結構,看起來就像是:

+----+------------+-------------------+--------------+-----------------+---------------------+ 
| id | ip   | mac    | opened_ports | vendor   | date    | 
+----+------------+-------------------+--------------+-----------------+---------------------+ 
| 1 | 10.20.1.19 | fc:15:b4:31:77:76 | NULL   | Hewlett Packard | 2016-02-15 15:50:19 | 
| 2 | 10.20.1.20 | e8:39:35:25:dd:36 | NULL   | Hewlett Packard | 2016-02-15 15:50:19 | 
| 3 | 10.20.1.21 | 8c:dc:d4:5d:21:7b | NULL   | Hewlett Packard | 2016-02-15 15:50:19 | 
| 4 | 10.20.1.18 | 38:ea:a7:6f:d9:05 | NULL   | Hewlett Packard | 2016-02-15 16:02:09 | 
| 5 | 10.20.1.19 | fc:15:b4:31:77:76 | NULL   | Hewlett Packard | 2016-02-15 16:02:09 | 
| 6 | 10.20.1.20 | e8:39:35:25:dd:36 | NULL   | Hewlett Packard | 2016-02-15 16:02:10 | 
| 7 | 10.20.1.21 | 8c:dc:d4:5d:21:7b | NULL   | Hewlett Packard | 2016-02-15 16:02:10 | 
+----+------------+-------------------+--------------+-----------------+---------------------+ 

這是進口的信息,而信息的開放的端口。

+0

您是否決定使用數據庫佈局?請[編輯]你的問題並分享。它看起來像你需要的是規範你的數據庫。 – simbabque

+0

我已經共享了數據庫結構。 – user2642601

+0

什麼數據類型是'opened_ports'? – simbabque

回答

0

低於初始打印語句print "$mac $vendor ";你知道在這一點上MAC廠商主機和日期,以便prepare與端口號

然後一個佔位符(?)在該行的INSERT語句打印端口號增加一個執行在佔位符位置

端口語句來完成的報告用這樣

create table scan (
    id int, 
    ip char(15), 
    mac char(20), 
    opened_ports int, 
    vendor varchar(255), 
    d datetime 
); 

這裏的模式是基於測試數據你的例子上述

INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(1,'10.20.1.19','fc:15:b4:31:77:76',25,'Hewlett Packard','2016-02-15 15:50:19'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(2,'10.20.1.20','e8:39:35:25:dd:36',80,'Hewlett Packard','2016-02-15 15:50:19'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(3,'10.20.1.21','8c:dc:d4:5d:21:7b',8080,'Hewlett Packard','2016-02-15 15:50:19'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(4,'10.20.1.18','38:ea:a7:6f:d9:05',137,'Hewlett Packard','2016-02-15 16:02:09'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(5,'10.20.1.19','fc:15:b4:31:77:76',443,'Hewlett Packard','2016-02-15 16:02:09'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(6,'10.20.1.20','e8:39:35:25:dd:36',8080,'Hewlett Packard','2016-02-15 16:02:10'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(7,'10.20.1.21','8c:dc:d4:5d:21:7b',22,'Hewlett Packard','2016-02-15 16:02:10'); 

,這裏是一個查詢所需

select ip,mac,GROUP_CONCAT(opened_ports) as port,vendor, d from scan group by ip; 
+1

問題是可能有相同IP地址的任意數量的端口號。 – reinierpost

+0

數據庫中的每一行都是由「id」而不是「ip」唯一的,因此可以插入多個具有相同ip的行 – Vorsprung

+0

其實你不知道。 OP在這個問題上沒有這樣說。可能還有一個獨特的索引。 – simbabque

1

Your database is not normalized,使輸出。你有一個基本的1:N關係,每行可以有零個或多個opened_ports

解決該問題的正確方法是創建第二個表,並且每id有N行。這將是這個樣子:

+-------+--------------+ 
| id_fk | opened_ports | 
+-------+--------------+ 
| 1 | 22   | 
| 1 | 80   | 
| 3 | 22   | 
+-------+--------------+ 

然後你刪除列opened_ports來回您的主表,並通過id它們連接。

在你的Perl程序中,你現在需要做兩個插入。第一個將用於大型表格,這也將創建您的(可能是auto_increment)id。您可以致電$dbh->last_insert_id取回。之後,您可以使用它在保存端口的小型表上執行後續的第二次插入語句(或組合的語句)。