我是Perl的新手,为了练习我正在编写一个简单的perl脚本来检查我的家庭网络是否有可用的ip地址,并检查他们的mac地址,供应商和打开的端口。 我想把所有那些信息都放在mysql db中。 这是我的代码:
#!/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 :(得分: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
来获取它。之后,使用它在保存端口的小型表上执行后续的第二个插入语句(或组合的语句)。
答案 1 :(得分:0)
在初始打印语句print "$mac $vendor ";
下面,您知道此时的mac供应商主机和日期,因此prepare
一个插入语句,其中包含占位符(?)
的端口号
然后在打印端口号的行处添加一个执行语句,其中端口位于占位符位置
要进行报告,请使用这样的模式
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;