jerick1976 has asked for the wisdom of the Perl Monks concerning the following question:

Screaming Uncle here and I'm sure I'll smack myself in the forehead once this is fixed. I have a subroutine that I call from another file to select where to store a database during creation based on available storage volume and percent of available space on the provided volumes. The subroutine is successfully called on five out of six RHEL 5 Linux systems. However, one system continues to report the following error when attempting to call the subroutine externally.

wwwin-git-rtp:145> /usr/local/bin/perl foo Undefined subroutine &gitadm_shell_commands::select_storage called at foo line 13.

Here is the impacted code :
#!/usr/local/bin/perl use strict; use warnings; use List::Util; use lib "/git_scripts/lib"; use gitadm_general_tools(); use gitadm_logparse_commands(); use gitadm_shell_commands(); my (@data_volumes,@error_log,@size,@partitions); my $storage_broken = gitadm_shell_commands::select_storage(); my $storage = select_storage(); print "$storage \n"; sub error { # Stores strings passed to it for later use in logging and emails my @strs = shift; for my $string(@strs) { push @error_log, "$string\n"; } } sub select_storage { my $known = shift; my $fstab = "/etc/fstab"; my ($percent,$check); my $use = "none"; # Replaced with file path if < $lowest my $lowest = "95"; # Blocks repo creation if value is >= 95 # Detect known or best volume to use for repo creation if (not $known) { open my $VOLUMES,'<', $fstab or die "$!"; @partitions = <$VOLUMES>; } else { push(@partitions, $known); } @partitions = grep/data/, @partitions; for my $p(@partitions) { my @parse_volumes = split(' ', $p); my @volume = grep/data/, @parse_volumes; push(@data_volumes, @volume); } for my $d(@data_volumes) { my $df_out = `/bin/df $d`; my @space = split(' ', $df_out); @space = grep(/\d/, @space); @space = grep/%/, @space; @space = grep(defined, @space); for my $s(@space) { my @percentages = split('%', $s); my @precentages = grep(defined, @percentages); $check = join("",@percentages); if ("$check" < "$lowest") { $lowest = "$check"; $use = $d; } } } if ($use eq "none") { error("Insuffcient storage available to create the requested +repository"); } else { return $use; } }

When copied to the local script and called as above, the impacted server successfully accesses the subroutine. I use the exact same environment, dot files, and perl version on all servers. All of the servers are running the exact same Linux image and patch level so I am at a loss as to why my code would execute differently on this one server and fine on the other five. What else should I check?

Replies are listed 'Best First'.
Re: random undefined sub error
by choroba (Cardinal) on Apr 10, 2013 at 13:08 UTC
    The first thing to check is the file /git_scripts/lib/gitadm_shell_commands.pm. Does it exist and contain the definition of select_storage? Is it really loaded by the script?
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      > Is it really loaded by the script?

      Well, according to his code, importer is never called since he explicitly uses empty lists after use ...

      > > use gitadm_shell_commands();

      Cheers Rolf

      ( addicted to the Perl Programming Language)

        importer is never called
        It depends on how far the modules follow the common practices (look at their names). Try:

        script.pl:

        #!/usr/bin/perl use warnings; use strict; use Ugly (); puke('Where does it come from?');

        Ugly.pm:

        package Ugly; use warnings; use strict; my $package = (caller)[0]; sub puke { warn @_; } { no strict 'refs'; *{$package . '::puke'} = \&puke; } __PACKAGE__
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      It does exist. It is linked in from an NFS mount point (NAS volume). sub select_storage does indeed exist within the gitadm_shell_commands.pm file. I have tried inserting a require statement to check to see if the module was loaded and did not receive an error. The addition had no affect on the error. Since the require statement seemed unnecessary so I removed it prior to posting.

        Could you possibly forget to define a package gitadm_shell_commands in your gitadm_shell_commands.pm file?

        Try checking symbol table for your sub in case it's left defined somewhere else:

        { no strict 'subs'; sub print_subs { for (keys %{$_[0]}) { next if $_ eq $_[0]; print "$_[0]$_\n" if defined *{$_}{CODE}; print_subs($_[0].$_) if /::$/; # dirty hack } } print_subs("main::"); }

Re: random undefined sub error
by Anonymous Monk on Apr 10, 2013 at 13:01 UTC

    What else should I check?

    %INC, and naturally the code of the modules you're using

Re: random undefined sub error
by LanX (Saint) on Apr 10, 2013 at 13:06 UTC
    is this line 13?

    > my $storage = select_storage();

    do you really use the same gitadm_shell_commands.pm and always with an empty list to overide the ->importer() ?

    Cheers Rolf

    ( addicted to the Perl Programming Language)

    EDIT: clarified the importer part.

      No, the empty list is only used when a calling script cannot provide a valid path for the subroutine. Then the sub performs a more costly search on the system.

        > Then the sub performs a more costly search on the system.

        well this fragile construct is most likely the source of your problems. Good luck tracking!

        Simple solution: avoid naming your local sub like an (potentially) imported one.

        Cheers Rolf

        ( addicted to the Perl Programming Language)

        DOH. think before I type.... Yes I generally do use an empty list in the use statement and call just what I need when I need it within the code.