【问题标题】:Debug a Perl script调试 Perl 脚本
【发布时间】:2012-12-30 09:18:59
【问题描述】:

我已经对 Perl 脚本调试进行了一些研究,但找不到我想要的。

让我在这里解释一下我的问题。

我有一个 Perl 脚本,它没有进入最后一个 while 循环,似乎因为它没有按照指示在里面打印任何内容。

所以,我想知道有没有更简单的方法可以一一查看所有行,就像我们在 shell 脚本中看到的那样

set -x

这是我的 Perl 脚本代码

#!/usr/bin/perl -w

my $ZONEADM = "/usr/sbin/zoneadm list -c";

use strict;
use diagnostics;
use warnings;

system("clear");
print "Enter the app\n";
chomp(my $INS = <>);

print "\nEnter the Symmitrix ID\n";
chomp(my $SYMM = <>);

print "\nEnter the Server\n";
chomp(my $SRV = <>);

print "\nEnter the devices\n";
while (<>) {
  if($_ !~ m/(q|quit)/) {    
    chomp($_);
    my $TEMP_FILE = "/export/home/ptiwari/scripts/LOG.11";
    open (my $FH, '>>', $TEMP_FILE);
    my @arr = split(/:/, $_);
    if($arr[3]) {
      print $FH "/".$INS."db/".$arr[0]."  ".$SYMM."  ".$arr[1]."  ".$arr[2]."  ".$arr[3]."\n";
    }
    else {
      print $FH "/".$INS."db/".$arr[0]."  ".$SYMM."  ".$arr[1]."  ".$arr[2]."\n";
    }
    undef @arr;
    close $FH;
  }
  else {
    exit;
  }
}

my $IS_ZONE = qx($ZONEADM|grep -i $SRV|grep -v global);
if($IS_ZONE) {
  $IS_ZONE = "yes";
}
else {
  $IS_ZONE = "no";    
}    

open(my $FLH, '<', "/export/home/ptiwari/scripts/LOG.11");
my @lines;
while(<$FLH>) {
  my ($GLOBAL_MTPT, $SYM, $SYM_DEV, $SIZE, $NEWFS) = split;
  print $GLOBAL_MTPT."  ".$SYM."  ".$SYM_DEV;
  print "\n";
}

我已经尝试过perl -d,但它没有显示任何可以帮助我解决为什么它没有进入 while 循环的问题。

【问题讨论】:

  • 如果你对文件有读写权限,它应该进入循环。您应该通过添加or die $! 来检查open 语句的返回值。
  • 我尝试使用 $!但它没有给出任何信息。我对文件有 rw 访问权限
  • 那条评论什么也没说。你试过如何使用它,在哪里? $! 仅在出现问题时设置。如果你有 rw 访问权限,那么你的 open 应该可以工作,$! 当然不会被设置。

标签: perl shell


【解决方案1】:

您的while(&lt;&gt;) 循环没有合理的终止条件。 /q|quit/ 正则表达式有问题。

  1. 如果任何行包含qquit,则退出整个脚本。如果设备描述包含quillacquisition 之类的内容,您也将退出。意外输入q 的效果类似于CtrlC

  2. 完成循环并继续执行脚本的唯一方法是发送 EOF。这需要用户将 CtrlD 打到键盘上,或者简单地结束文件。然后您的脚本继续。

这个脚本还有其他一些错误/奇怪的地方。 主要批评: (a) 全大写变量被非正式地保留给 Perl 和实用模块。小写或混合大小写变量也可以。 (b) 您的脚本包含相当多的冗余代码。要么将其重构为subs,要么重写你的逻辑

这是一个可能更容易调试/可能不包含某些错误的示例重写。

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

use constant DEBUG_FLAG => 1;  # set to false value for release
my $zoneadm_command = "/usr/sbin/zoneadm list -c";
my $temp_file_name = "/export/home/ptiwari/scripts/LOG.11";

sub prompt { print "\n", $_[0], "\n"; my $answer = <>; chomp $answer; return $answer }
sub DEBUG  { print STDERR "DEBUG> ", @_, "\n" if DEBUG_FLAG }

system("clear");
my $app_name = prompt("Enter the app");
my $symm_id  = prompt("Enter the Symmitrix ID");
my $server   = prompt("Enter the server name");
print "Enter the devices.\n";
print qq(\tTo terminate the script, type "q" or "quit".\n);
print qq(\tTo finish the list of devices, type Ctrl+D.\n);

open my $temp_file, ">>", $temp_file_name
    or die "Can't open log file: $!";

while (<>) {
  chomp; # remove trailing newline
  exit if /^q(?:uit)?$/; # terminate the script if the input line *is* `q` or `quit`. 
  my @field = split /:/;
  # grep: select all true values
  @field = grep {$_} ("/${app_name}db/$field[0]", $symm_id, @field[1 .. 3]);
  print $temp_file join("  ", @field), "\n";
}
close $temp_file;

DEBUG("finished the reading loop");

# get the zones with only *one* extra process
my @zones = 
    grep {not /global/}
    grep {/\Q$server\E/i}
    map  {chomp; $_}
        qx($zoneadm_command);
my $is_zone = @zones ? "yes" : "no";

DEBUG("Am I in the zone? $is_zone");

open my $device_file, "<", $temp_file_name or die "Can't open $temp_file_name: $!";

while (<$device_file>) {
  chomp;
  my ($global_mtpt, $sym, $sym_dev) = split;
  print join("  ", $global_mtpt, $sym, $sym_dev), "\n";
  # or short: print join("  ", (split)[0 .. 2]), "\n";
}

【讨论】:

  • 非常感谢 amon 分享这么好的代码。这对我很有帮助。我接受了你的回答。
【解决方案2】:

你需要这样的东西来进入脚本:

http://www.devshed.com/c/a/Perl/Using-The-Perl-Debugger/

【讨论】:

    【解决方案3】:

    你真的可以使用调试器:http://perldoc.perl.org/perldebug.html

    但是,如果您喜欢像 bash -x 一样进行跟踪,请查看以下讨论: http://www.perlmonks.org/?node_id=419653

    【讨论】:

      【解决方案4】:

      Devel::Trace Perl 模块旨在模仿 sh -x 跟踪 shell 程序。

      【讨论】:

        【解决方案5】:

        尝试删除最后一个 open 语句中的“my $”和最后一个 while 语句中的“$”。或者更好的是,试试这个:

        open(my FLH, '<', "/export/home/ptiwari/scripts/LOG.11");
        
        my @lines = <FLH>;
        foreach (@lines) {
            my ($GLOBAL_MTPT, $SYM, $SYM_DEV, $SIZE, $NEWFS) = split;
            print $GLOBAL_MTPT." ".$SYM." ".$SYM_DEV;
            print "\n";
        }
        

        让我知道结果。

        【讨论】:

        • 不是我的反对意见,但我能理解为什么。这只是个坏建议。使用词法文件句柄,如果不需要,不要乱用文件。而且,它是print "$GLOBAL_MTPT $SYM $SYM_DEV\n"
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-06
        相关资源
        最近更新 更多