perl代码执行顺序

时间:2013-07-04 14:37:34

标签: linux perl

以下让我发疯。

为了清晰起见,我提交了整个功能。这里的目的是在每次Linux镜像子设备出现故障或删除子设备时记录错误。我只需要每次都有一条消息。如果子设备尚未从镜像中完全移除并且处于故障状态,则mdadm命令输出始终显示已删除的行和有故障的行。我只想在这种情况下只记录子设备故障部分而不是删除部分。

设备已从镜像中移除,不再出现错误,但仅删除了。在这种情况下,我需要记录删除的错误。

为此,我使用变量$myfaulty并解析mdadm --detail $md_dev输出。 问题是第一个出现的代码部分是第二个。

以下代码首先出现:

elsif ($subdevice_status =~ /faulty/) {
_msg("ERROR: MD device $device status $device_status, sub-device status $subdevice_status " );
_mylog('err', "ERROR: faulty MD $device $device_status: sub-device $subdevice ($subdevice_role): status $subdevice_status " );
  $myfaulty = 1;

这是第二个:

elsif ($subdevice_status =~ /removed/ && $myfaulty != 1 ) {
 _msg("ERROR: MD device $device status $device_status, sub-device status $subdevice_status " );
 printf("The removed part: $myfaulty, $device, $raid_type \n");
 _mylog('err', "ERROR: MD device $device status $device_status, sub-device $subdevice_status " );

$ myfaulty变量评估首先发生在第二个代码块上,然后发生在第一个代码块上。

有什么想法吗?

谢谢, 乔治

子代码

# checks all MD volumes it finds on the system
sub check_md() {
my $MDADMCMD = "";
my $device = "";
my $subdevice = "";
my $device_status = "";
my $subdevice_status = "";
my $raid_type = "";
my $subdevice_role = "";
my $raid_count = 0;
my $lines = 0;
my $myfaulty = 0;

    foreach(@mdadm_paths) {
            if( -e $_ ) { $MDADMCMD = $_; _debug("using mdadm in $MDADMCMD"); last; }
    }
    if($MDADMCMD eq "") { _msg("MD not configured on this system (mdadm not found) - "); return; }
    open MDSCAN, "-|", "$MDADMCMD --detail --scan --verbose 2>&1" || die "can't run: $!";
    while(<MDSCAN>) {
            $lines++;
            if($_ =~ /^ARRAY/) {
                    $_ =~ /^ARRAY\s+(\S+)\s+level=(\S+)\s+/;
                    $device = $1;
                    $raid_type = $2;
                    $raid_count++;
                    _debug("found MD device $device, raid-level $raid_type");
            open MDDETAIL, "-|", "$MDADMCMD --detail $device" || die "can't run: $!"; while(<MDDETAIL>) {
    printf($_);
                            if($_ =~ /\s+State\s+:\s+(.+)$/) { # md device status
                                    $device_status = $1;
                                    chomp($device_status);
                                    _debug("device status: $device_status");


                                    if($device_status !~ /clean$/) {
                                            change_status("CRITICAL");
                                            $md_status = "CRITICAL";

                            }

                             if($_ =~ /^\s+(\d+|-)\s+(\d+|-)\s+(\d+|-)\s+(\d+|-)\s+(\w+)\s+(\w+)\s+(\S+)\s*$/) {
                                    $subdevice_status = $5; $subdevice_role = $6; $subdevice = $7;
                                    _debug("device:$device - subdevice:$subdevice - role:$subdevice_role - status:$subdevice_status");
                                    if($subdevice_status !~ /active/) {
                                            change_status("CRITICAL");
                                            $md_status = "CRITICAL";
                                            _msg("MD $device, sub-device $subdevice ($subdevice_role): status $subdevice_status - ");
                                            if ($subdevice_role =~ /rebuilding/) {
                                            _mylog('warning', "WARNING: MD $device $device_status: sub-device $subdevice ($subdevice_role): status $subdevice_status " );
                                             }
                                            elsif ($subdevice_status =~ /faulty/) {
                                            _msg("ERROR: MD device $device status $device_status, sub-device status $subdevice_status " );
                                            _mylog('err', "ERROR: faulty MD $device $device_status: sub-device $subdevice ($subdevice_role): status $subdevice_status " );
                                            $myfaulty = 1;
                                            printf("Faulty is here:  $myfaulty, $subdevice_status, $raid_type \n");
                                            }
                                            elsif ($subdevice_status =~ /removed/ && $myfaulty != 1 ) {
                                                     _msg("ERROR: MD device $device status $device_status, sub-device status $subdevice_status " );
                                                     printf("The removed part: $myfaulty, $device, $raid_type \n");
                                                     _mylog('err', "ERROR: MD device $device status $device_status, sub-device $subdevice_status " );

                                            }
                                            else {
                                            _msg("MD $device, sub-device $subdevice ($subdevice_role): status $subdevice_status - ");
                                            _mylog('err', "ERROR: after faulty MD $device $device_status: sub-device $subdevice ($subdevice_role): status $subdevice_status " );
                                            }
                                    }
                                            else { _verbosemsg("MD $device, sub-device $subdevice ($subdevice_role): status OK - "); }
                             # Need to also catch subdevices that have been removed and don't show up anymore.
                    }
                    if ($_ =~ /^\s+(\d+|-)\s+(\d+|-)\s+(\d+|-)\s+(\d+|-)\s+(\w+)\s*$/) {
                                   $subdevice_status = $5;
                                     _debug("device:$device - subdevice:$subdevice - role:$subdevice_role - status:$subdevice_status");

                                            printf("The removed part: $myfaulty, $device, $raid_type \n");
                                    if ($subdevice_status =~ m/removed/ && $myfaulty != 1 ) {
                                            _msg("ERROR: MD device $device status $device_status, sub-device status $subdevice_status " );
                                            printf("The removed part: $myfaulty, $device, $raid_type \n");
                                            _mylog('err', "ERROR: MD device $device status $device_status, sub-device $subdevice_status " );
                                            }
                            }
                    } #while(<MDDETAIL>)
                    close(MDDETAIL);
            }
    }
    close(MDSCAN);
    # no md devices found, but command output wasn't empty
    if($raid_count == 0 && $lines > 0) { _msg("MD status is UNKNOWN (can't get configuration info) - "); }
    elsif($raid_count == 0) { _msg("MD not configured on this system - "); }
    elsif($md_status eq "OK" && not defined $verbOutput) { _msg("MD Status is OK - ");  }  }

mdadm --detail output

/dev/md0:
    Version : 0.90
Creation Time : Mon Mar  4 12:53:19 2013
 Raid Level : raid1
 Array Size : 521984 (509.84 MiB 534.51 MB)
Used Dev Size : 521984 (509.84 MiB 534.51 MB)
 Raid Devices : 2
Total Devices : 2
Preferred Minor : 0
Persistence : Superblock is persistent

Update Time : Thu Jul  4 16:27:46 2013
      State : clean, degraded
Active Devices : 1
Working Devices : 1
Failed Devices : 1
Spare Devices : 0

       UUID : 3a3bd078:31678889:9485a7cf:e1283d32
     Events : 0.438

Number   Major   Minor   RaidDevice State
   0       0        0        0      removed
   1       8       33        1      active sync   /dev/sdc1

   2       8       17        -      faulty spare   /dev/sdb1

2 个答案:

答案 0 :(得分:1)

我试图查看你的代码,但它相当痛苦,并且不适合我的电脑屏幕,所以我想告诉你你可以做什么而不是解析那个特定的输入。

首先,这是一个疏忽的陷阱:

open MDDETAIL, "-|", "$MDADMCMD --detail $device" || die "can't run: $!";

如果查看perldoc perlop,您会在优先级表中注意到||的优先级高于,(逗号)。这意味着上述陈述的确意味着:

open MDDETAIL, "-|", 
    ("$MDADMCMD --detail $device" || die "can't run: $!");

或者,换句话说,open的第三个参数变为字符串或die语句。因为这个字符串不是空的,所以它总是为真(毕竟它是一个常量),并且由于||短的curcuits,die语句永远不会发生。即使它可以,它也不再与open命令的返回值相关联。这是你应该做的:

open(my $fh, "<", $file) || die $!;     # use parentheses to override precedence
open my $fh, "<", $file  or die $!;     # use "or" which has lower precedence

主要问题

解析你的输入并不困难,只是有点挑剔。解析后,您可以轻松提取所需的部分。因此,不要编写复杂的循环和嵌套的if语句,而只是先将文本分开。

use strict;
use warnings;
use Data::Dumper;

my %data;
my $input;
{
    local $/;                              # disable input record separator
    $input = <DATA>;                       # read entire input into one string
}
my ($num) = $input =~ /\n\n(Number.*)/s;   # extract table part
$input =~ s/\n\n(Number.*)//s;             # remove from keys/values
my @vals = grep /\S/, split /\n+/, $input;
my $dev = shift @vals;
$data{Device} = $dev;                      # extract dev name
for (@vals) {
    if (/^\s*([^:]+)\s*:(.*)/) {
        $data{$1} = $2;                # parse and store the key/values
    } else { warn "Bad data: $_"; }
}
my @nums = split /\n+/, $num;
my $header = shift @nums;                  # remove header
for (@nums) {
    s/^\s+//;                              # remove leading whitespace
    my @items = split /\s{2,}/;            # split on 2 or more whitespace
    my $state = $items[4];
    my $dev = $items[5] // "N/A";          # use fields as required
    print "Device: $dev, State: $state\n";
    # do stuff
}
print Dumper \%data;                       # this is the key/values we stored

# below is sample input
__DATA__
/dev/md0:
    Version : 0.90
Creation Time : Mon Mar  4 12:53:19 2013
 Raid Level : raid1
 Array Size : 521984 (509.84 MiB 534.51 MB)
Used Dev Size : 521984 (509.84 MiB 534.51 MB)
 Raid Devices : 2
Total Devices : 2
Preferred Minor : 0
Persistence : Superblock is persistent

Update Time : Thu Jul  4 16:27:46 2013
      State : clean, degraded
Active Devices : 1
Working Devices : 1
Failed Devices : 1
Spare Devices : 0

       UUID : 3a3bd078:31678889:9485a7cf:e1283d32
     Events : 0.438

Number   Major   Minor   RaidDevice State
   0       0        0        0      removed
   1       8       33        1      active sync   /dev/sdc1
   2       8       17        -      faulty spare   /dev/sdb1

<强>输出:

Device: N/A, State: removed
Device: /dev/sdc1, State: active sync
Device: /dev/sdb1, State: faulty spare
$VAR1 = {
          'Events ' => ' 0.438',
          'UUID ' => ' 3a3bd078:31678889:9485a7cf:e1283d32',
          'Persistence ' => ' Superblock is persistent',
          'Active Devices ' => ' 1',
          'Array Size ' => ' 521984 (509.84 MiB 534.51 MB)',
          'Spare Devices ' => ' 0',
          'Device' => '/dev/md0:',
          'State ' => ' clean, degraded',
          'Total Devices ' => ' 2',
          'Preferred Minor ' => ' 0',
          'Creation Time ' => ' Mon Mar  4 12:53:19 2013',
          'Used Dev Size ' => ' 521984 (509.84 MiB 534.51 MB)',
          'Failed Devices ' => ' 1',
          'Version ' => ' 0.90',
          'Raid Devices ' => ' 2',
          'Raid Level ' => ' raid1',
          'Working Devices ' => ' 1',
          'Update Time ' => ' Thu Jul  4 16:27:46 2013'
        };

答案 1 :(得分:0)

问题似乎是你正在记录你的输出,因为你在决定要输出什么之前解析每一行但你需要知道mdadm --detail output中的所有行。

您需要重构那些在文件解析循环结束后检查$ subdevice_status的代码,这样您就可以检查是否已删除AND $ myfaulty不正确。您需要在变量中存储更多信息,而不是直接记录它们。