update-mac-vendors.pl 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #!/usr/bin/perl
  2. #
  3. # Copyright (C) Roman Dmitriev, rnd@rajven.ru
  4. #
  5. use utf8;
  6. use warnings;
  7. use Encode;
  8. use open qw(:std :encoding(UTF-8));
  9. no warnings 'utf8';
  10. use English;
  11. use FindBin '$Bin';
  12. use lib "/opt/Eye/scripts";
  13. use Data::Dumper;
  14. use eyelib::config;
  15. use eyelib::main;
  16. use eyelib::logconfig;
  17. use eyelib::database;
  18. use eyelib::common;
  19. use eyelib::net_utils;
  20. use strict;
  21. use warnings;
  22. binmode(STDOUT, ':encoding(utf8)');
  23. binmode(STDERR, ':encoding(utf8)');
  24. my $clean_run = $ARGV[0] || '';
  25. my $batch_size = 1000;
  26. # Очищаем таблицу если нужно
  27. if ($clean_run eq 'clean') {
  28. do_sql($dbh, "TRUNCATE TABLE mac_vendors");
  29. print "Таблица очищена\n";
  30. }
  31. # Получаем существующие OUI из базы
  32. my %existing_oui;
  33. if ($clean_run ne 'clean') {
  34. print "Получаем существующие OUI из базы...\n";
  35. my $sth = $dbh->prepare("SELECT oui FROM mac_vendors");
  36. $sth->execute;
  37. while (my ($oui) = $sth->fetchrow_array) {
  38. $existing_oui{$oui} = 1;
  39. }
  40. $sth->finish;
  41. print "Найдено существующих записей: " . scalar(keys %existing_oui) . "\n";
  42. }
  43. my $filename = "/opt/Eye/scripts/utils/mac-oids/manuf.csv";
  44. open(my $fh, '<:encoding(utf8)', $filename)
  45. or die "Не удалось открыть файл $filename: $!";
  46. print "Обработка файла...\n";
  47. my @batch_data;
  48. my $total_processed = 0;
  49. my $total_inserted = 0;
  50. my $line_num = 0;
  51. while (my $line = <$fh>) {
  52. $line_num++;
  53. chomp $line;
  54. # Пропускаем пустые строки
  55. next if $line =~ /^\s*$/;
  56. # Пропускаем заголовок
  57. next if $line_num == 1 && $line =~ /^MAC Prefix/;
  58. # Разбиваем на поля
  59. my @fields = split(/;/, $line, 3);
  60. my $oui = $fields[0] || '';
  61. my $company = $fields[1] || '';
  62. my $address = $fields[2] || '';
  63. # Убираем кавычки если есть
  64. $oui =~ s/^\"|\"$//g;
  65. $company =~ s/^\"|\"$//g;
  66. $address =~ s/^\"|\"$//g;
  67. # Очищаем данные
  68. $oui = trim($oui);
  69. $company = trim($company);
  70. $address = trim($address);
  71. # Пропускаем если нет OUI
  72. next unless $oui && $oui =~ /\S/;
  73. # Убираем маску подсети
  74. $oui =~ s{/[0-9]+}{};
  75. # Нормализуем MAC
  76. $oui = mac_splitted($oui);
  77. # Проверяем минимальную длину
  78. next unless length($oui) >= 8;
  79. # Пропускаем если уже есть в базе
  80. next if $existing_oui{$oui};
  81. # Добавляем в пакет
  82. push @batch_data, [$oui, $company, $address];
  83. $total_processed++;
  84. # Вставляем пакет при достижении размера
  85. if (@batch_data >= $batch_size) {
  86. $total_inserted += insert_batch_simple(\@batch_data);
  87. @batch_data = ();
  88. }
  89. # Прогресс
  90. print "Обработано строк: $line_num\r" if ($line_num % 1000 == 0);
  91. }
  92. close $fh;
  93. # Вставляем остатки
  94. if (@batch_data) {
  95. $total_inserted += insert_batch_simple(\@batch_data);
  96. }
  97. print "\n\nИтоги:\n";
  98. print "Обработано строк: $total_processed\n";
  99. print "Добавлено записей: $total_inserted\n";
  100. print "Done!\n";
  101. exit;
  102. # Простая пакетная вставка
  103. sub insert_batch_simple {
  104. my ($batch_ref) = @_;
  105. my @data = @$batch_ref;
  106. return 0 unless @data;
  107. my $sth = $dbh->prepare("
  108. INSERT INTO mac_vendors (oui, companyname, companyaddress)
  109. VALUES (?, ?, ?)
  110. ");
  111. $dbh->begin_work;
  112. my $inserted = 0;
  113. foreach my $row (@data) {
  114. my ($oui, $company, $address) = @$row;
  115. eval {
  116. $sth->execute($oui, $company, $address);
  117. $inserted++;
  118. };
  119. if ($@) {
  120. warn "Ошибка при вставке $oui: $@\n";
  121. }
  122. }
  123. $dbh->commit;
  124. $sth->finish;
  125. return $inserted;
  126. }