无论在管理LVS配置中,对keepalive的配置文件管理是必不可少的,解析配置文件也是核心功能之一,现在把自己写的一些思路分享给大家~
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use JSON; use re ‘eval‘; #将keepalived.conf 格式化为json数据 my $file = "/Users/machenlong/Downloads/keepalived.conf"; open FH, $file or die "$!"; #一次行读取整个文件 my $str = do { local $/; <FH> }; #定义树形中的键值对 my $treeKey = { vrrpKey => { state => 1, interface => 1, virtual_router_id => 1, priority => 1, advert_int => 1, }, virtualKey => { delay_loop => 1, lb_algo => 1, lb_kind => 1, protocol => 1 }, realKey => { realKey0 => { weight => 1, }, realKey1 => { TCP_CHECK => 1, HTTP_GET => 1 }, realKey2 => { connect_timeout => 1, nb_get_retry => 1, delay_before_retry => 1, connect_port => 1, }, realKey3 => { url => 1, path => 1, status_code => 1 } } }; my $hash; my $re = qr/(.*)s+{(?{local $a=0})(?>(?:([^{}]+)(?{push @{$hash->{$1}},$2;})| #将匹配到得内容push到$hash #固化分组,减少回朔。 {(?{$a++})| #遇到开括号$a+1 }(?(?{$a!=0})(?{$a--})| #如果$a不等于0则遇到闭括号$a-1 (?!)))*)(?(?{$a!=0})(?!))}/x; # 否则继续匹配,如果继续遇到$a不等于0 继续匹配到行尾 #处理注释 $str =~ s/ #.*$//mg; 1 while ( $str =~ /$re/g ); my ( $formatHash, $vrrpFormat ); for my $key ( keys %$hash ) { for ( @{ $hash->{$key} } ) { vrrp_format( $key, $_, $treeKey ); } } my $confFormat = real_format( $vrrpFormat, $treeKey ); print encode_json $confFormat; sub vrrp_format { my ( $varrKey, $varrParam, $treeKey ) = @_; my ( $realIp, $realPort, $key3, @unParams ); if ( $varrKey =~ /(global_defs)/ ) { my @params = split ‘ ‘, $varrParam; $vrrpFormat->{$1}->{ $params[0] } = $params[1]; } #vvrp 分解 elsif ( $varrKey =~ /(vrrp.*?)s+(w+)/ ) { my ( $key, $value ) = ( $1, $2 ); my @params = split ‘ ‘, $varrParam; my $ips; for ( 0 .. $ #params ) { my @v = splice @params, 0, 2; if (@v) { if ( $treeKey->{vrrpKey}->{ $v[0] } ) { $vrrpFormat->{$key}->{$value}->{ $v[0] } = $v[1]; } else { for (@v) { #IP处理 if (/(d+.){3}d+/) { push @{ $vrrpFormat->{$key}->{$value} ->{virtual_ipaddress} }, $_; } #auth字段处理 elsif (/auth_/) { $vrrpFormat->{$key}->{$value}->{authentication} ->{ $v[0] } = $v[1]; } } } } } } #virtual_server处理 elsif ( $varrKey =~ /(virtual_server)s+((?:d+.){3}d+)s+(d+)/ ) { #键值名,IP,端口 my ( $key, $ip, $port ) = ( $1, $2, $3 ); my @params = split ‘ ‘, $varrParam; for ( 0 .. $ #params ) { #切分数组前两个元素 my @v = splice @params, 0, 2; if (@v) { if ( $treeKey->{virtualKey}->{ $v[0] } ) { $vrrpFormat->{$key}->{$ip}->{$port}->{ $v[0] } = $v[1]; } else { #不匹配定义的检测,重新写回@params unshift @params, @v; } } } if (@params) { #将剩余的params写回总hash,real_serverArr临时数组 push @{ $vrrpFormat->{$key}->{$ip}->{$port}->{real_serverArr} }, @params; } } } sub real_format { my ( $vrrpFormat, $treeKey ) = @_; for my $sIp ( keys %{ $vrrpFormat->{virtual_server} } ) { my $portHash = $vrrpFormat->{virtual_server}->{$sIp}; for my $port ( keys %$portHash ) { my @realArr = @{ $portHash->{$port}->{real_serverArr} }; #realserver IP、port 位置 my ($realIp, $realPort, @pos); #3级 4级 键值类型,数值 my ( $key3, $key4, $value4, $key5 ); #查找IP的POS未知 for ( 0 .. $ #realArr ) { if ( $realArr[$_] =~ /(?:d+.){3}d+/ ) { push @pos, $_; } } my ( @realIp, @realPort ); my $cPos = 0; #根据位置,将IP端口放入数组 for (@pos) { push @realIp, splice @realArr, $_ - $cPos, 1; push @realPort, splice @realArr, $_ - $cPos, 1; $cPos += 2; } for my $realParam ( @realArr) { #根据real_server未知确定IP、端口未知 if ( $realParam eq "real_server" ) { $realIp = shift @realIp; $realPort = shift @realPort; next; } #遇到TCP_CHECK HTTP_GET url作为分支,存入key3 if ( $realParam =~ /(TCP_CHECK)/ ) { $key3 = $1; } elsif ( $realParam =~ /(HTTP_GET)/ ) { $key3 = $1; } elsif ( $realParam =~ /(url)/ ) { $key5 = $1; } if ( !$key4 and $realParam !~ /HTTP_GET|TCP_CHECK/ ) { $key4 = $realParam; } #匹配为键值对逻辑 if ( $key4 and !$value4 ) { #必须为数字 if ( $realParam =~ /^d+$/ ) { $value4 = $realParam; } #或者为url elsif ( $realParam =~ /https?:/// ) { $value4 = $realParam; } } if ( $key4 and $value4 and $key3 ) { # print "$realIp,$key3,$key4,$value4n"; #判断键值对是否在定义中存在 if ( $treeKey->{realKey}->{realKey0}->{$key4} ) { $portHash->{$port}->{real_server}->{$realIp} ->{$realPort}->{$key4} = $value4; } elsif ( $treeKey->{realKey}->{realKey2}->{$key4} ) { $portHash->{$port}->{real_server}->{$realIp} ->{$realPort}->{$key3}->{$key4} = $value4; } #url判断 elsif ($key5) { $portHash->{$port}->{real_server}->{$realIp} ->{$realPort}->{$key3}->{$key5}->{$key4} = $value4; } undef $key4; undef $value4; } #删除临时存储数组 delete $portHash->{$port}->{real_serverArr}; } } } return $vrrpFormat; }
时间: 2024-10-06 23:07:00