Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: undefined hash elements

by marinersk (Priest)
on Dec 19, 2013 at 00:03 UTC ( [id://1067744]=note: print w/replies, xml ) Need Help??


in reply to undefined hash elements

Summary of Problems: Blindly passing bad data around.
 

  • You are passing bad data to _percentage_to_decimal(), which is not doing any defensive data checking, and;
  • You are unconditionally using a hash key without checking its existence first.

I am able to reproduce your problem using the input data you specified (thank you for providing that). My line numbers are off by one from yours but otherwise it looks live I've matched your error:

#!/usr/bin/perl use strict; use warnings; my @headers = qw(name size used free capacity mount); my @df = &readDFfile('test.dat'); shift @df; # get rid of the header my %devices; for my $line (@df) { my %info; @info{@headers} = split /\s+/, $line; # note the hash slice $info{capacity} = _percentage_to_decimal($info{capacity}); $devices{ $info{mount} } = \%info; } # Change 12.3% to .123 sub _percentage_to_decimal { my $percentage = shift; $percentage =~ s{%}{}; return $percentage / 100; } # Now the information for each device is in a hash of hashes. # Show how much space is free in device /dev/ad4s1e print $devices{"/production/log"}{free} ; print "\n"; for my $info (values %devices) { # Skip to the next device if its capacity is not over 60%. next unless $info->{capacity} > .10; # Print some info about each device printf "%s is at %d%% with %dK remaining.\n", $info->{mount}, $info->{capacity}*100, $info->{free}; } exit; sub readDFfile { my ($rdofnm, @arglst) = @_; if (!defined $rdofnm) { $rdofnm = ''; } # -----[ Was command, now reading from file for testing purposes +]-------------- # my @df = `df -k`; # --------------------------------------------------------------- +--------------- my @df = (); if (open RDOFIL, '<', $rdofnm) { @df = <RDOFIL>; close RDOFIL; } # --------------------------------------------------------------- +--------------- return @df; } __END__ C:\Steve\Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef>perl -v This is perl 5, version 16, subversion 3 (v5.16.3) built for MSWin32-x +64-multi-thread (with 1 registered patch, see perl -V for more detail) Copyright 1987-2012, Larry Wall Binary build 1603 [296746] provided by ActiveState http://www.ActiveSt +ate.com Built Mar 13 2013 13:31:10 Perl may be copied only under the terms of either the Artistic License + or the GNU General Public License, which may be found in the Perl 5 source ki +t. Complete documentation for Perl, including FAQ lists, should be found +on this system using "man perl" or "perldoc perl". If you have access to + the Internet, point your browser at http://www.perl.org/, the Perl Home Pa +ge. C:\Steve\Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef>type test.dat Filesystem 1K-blocks Used Available Use% Mounted on /dev/mapper/VolGroup00-LogVol00 28313732 9816924 17035356 37% / /dev/sda1 101086 27516 68351 29% /boot tmpfs 2987896 0 2987896 0% /dev/shm /dev/mapper/VolGroupPROD-ExportHome 15481840 3495504 11199904 24% /export/home /dev/mapper/VolGroupPROD-Production 15481840 1523692 13171716 11% /production /dev/mapper/VolGroupPROD-ProdLog 30963708 20410952 8979892 70% /production/lo +g /dev/mapper/VolGroupPROD-ProdArchive 10313016 1693640 8095500 18% /production/ar +chive C:\Steve\Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef>perl testdf2.pl Use of uninitialized value $percentage in substitution (s///) at testd +f2.pl line 20. Use of uninitialized value $percentage in division (/) at testdf2.pl l +ine 21. Use of uninitialized value $info{"mount"} in hash element at testdf2.p +l line 14. Use of uninitialized value $percentage in substitution (s///) at testd +f2.pl line 20. Use of uninitialized value $percentage in division (/) at testdf2.pl l +ine 21. Use of uninitialized value $info{"mount"} in hash element at testdf2.p +l line 14. Use of uninitialized value $percentage in substitution (s///) at testd +f2.pl line 20. Use of uninitialized value $percentage in division (/) at testdf2.pl l +ine 21. Use of uninitialized value $info{"mount"} in hash element at testdf2.p +l line 14. Use of uninitialized value $percentage in substitution (s///) at testd +f2.pl line 20. Use of uninitialized value $percentage in division (/) at testdf2.pl l +ine 21. Use of uninitialized value $info{"mount"} in hash element at testdf2.p +l line 14. Use of uninitialized value $percentage in substitution (s///) at testd +f2.pl line 20. Use of uninitialized value $percentage in division (/) at testdf2.pl l +ine 21. Use of uninitialized value $info{"mount"} in hash element at testdf2.p +l line 14. 8979892 /production/log is at 70% with 8979892K remaining. / is at 37% with 17035356K remaining. /boot is at 28% with 68351K remaining. /export/home is at 24% with 11199904K remaining. /production is at 11% with 13171716K remaining. /production/archive is at 18% with 8095500K remaining.

I apologize for using my homespun debug module instead of Data::Dumper. Feel free to convert the debugging lines at your convenience, but you probably won't need them going forward.

In this debug version of the code, look in the results for where $percentage = ''. You pass bad data in to the subroutine, and it blindly starts trying to compute against it.

#!/usr/bin/perl use strict; use warnings; use debug; my @headers = qw(name size used free capacity mount); &debug::predebugdumplist("\@headers", \@headers); my @df = &readDFfile('test.dat'); &debug::predebugdumplist("\@df", \@df); shift @df; # get rid of the header &debug::predebugdumplist("\@df", \@df); my %devices; &debug::predebugdumplist("\%devices", \%devices); for my $line (@df) { &debug::predebug("\$line = '$line'\n"); my %info; &debug::predebugdumplist("\%info", \%info); @info{@headers} = split /\s+/, $line; # note the hash slice &debug::predebugdumplist("\%info", \%info); $info{capacity} = _percentage_to_decimal($info{capacity}); &debug::predebugdumplist("\%info", \%info); $devices{ $info{mount} } = \%info; &debug::predebugdumplist("\%devices", \%devices); } # Change 12.3% to .123 sub _percentage_to_decimal { my $percentage = shift; &debug::predebug("\$percentage = '$percentage'\n"); $percentage =~ s{%}{}; &debug::predebug("\$percentage = '$percentage'\n"); return $percentage / 100; } # Now the information for each device is in a hash of hashes. # Show how much space is free in device /dev/ad4s1e print $devices{"/production/log"}{free} ; print "\n"; for my $info (values %devices) { &debug::predebug("\$info = '$info'\n"); # Skip to the next device if its capacity is not over 60%. next unless $info->{capacity} > .10; &debug::predebug("Found \$info->{capacity} to be > .10\n"); # Print some info about each device printf "%s is at %d%% with %dK remaining.\n", $info->{mount}, $info->{capacity}*100, $info->{free}; } exit; sub readDFfile { my ($rdofnm, @arglst) = @_; if (!defined $rdofnm) { $rdofnm = ''; } # -----[ Was command, now reading from file for testing purposes +]-------------- # my @df = `df -k`; # --------------------------------------------------------------- +--------------- my @df = (); if (open RDOFIL, '<', $rdofnm) { @df = <RDOFIL>; close RDOFIL; } # --------------------------------------------------------------- +--------------- return @df; } __END__

The results follow -- WARNING: This is LONG.

C:\Steve\Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef>perl testdf3.pl > +testdf3.txt Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 38. Use of uninitialized value $percentage in substitution (s///) at testd +f3.pl line 40. Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 41. Use of uninitialized value $percentage in division (/) at testdf3.pl l +ine 43. Use of uninitialized value $info{"mount"} in hash element at testdf3.p +l line 31. Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 38. Use of uninitialized value $percentage in substitution (s///) at testd +f3.pl line 40. Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 41. Use of uninitialized value $percentage in division (/) at testdf3.pl l +ine 43. Use of uninitialized value $info{"mount"} in hash element at testdf3.p +l line 31. Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 38. Use of uninitialized value $percentage in substitution (s///) at testd +f3.pl line 40. Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 41. Use of uninitialized value $percentage in division (/) at testdf3.pl l +ine 43. Use of uninitialized value $info{"mount"} in hash element at testdf3.p +l line 31. Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 38. Use of uninitialized value $percentage in substitution (s///) at testd +f3.pl line 40. Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 41. Use of uninitialized value $percentage in division (/) at testdf3.pl l +ine 43. Use of uninitialized value $info{"mount"} in hash element at testdf3.p +l line 31. Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 38. Use of uninitialized value $percentage in substitution (s///) at testd +f3.pl line 40. Use of uninitialized value $percentage in concatenation (.) or string +at testdf3.pl line 41. Use of uninitialized value $percentage in division (/) at testdf3.pl l +ine 43. Use of uninitialized value $info{"mount"} in hash element at testdf3.p +l line 31. C:\Steve\Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef>type testdf3.txt @headers (C:\Steve\Perl/debug.pm:887): [name] [size] [used] [free] [capacity] [mount] @df (C:\Steve\Perl/debug.pm:887): [Filesystem 1K-blocks Used Available Use% Mounted o +n ] [/dev/mapper/VolGroup00-LogVol00 ] [ 28313732 9816924 17035356 37% / ] [/dev/sda1 101086 27516 68351 29% /boot ] [tmpfs 2987896 0 2987896 0% /dev/shm ] [/dev/mapper/VolGroupPROD-ExportHome ] [ 15481840 3495504 11199904 24% /export/h +ome ] [/dev/mapper/VolGroupPROD-Production ] [ 15481840 1523692 13171716 11% /producti +on ] [/dev/mapper/VolGroupPROD-ProdLog ] [ 30963708 20410952 8979892 70% /producti +on/log ] [/dev/mapper/VolGroupPROD-ProdArchive ] [ 10313016 1693640 8095500 18% /producti +on/archive ] @df (C:\Steve\Perl/debug.pm:887): [/dev/mapper/VolGroup00-LogVol00 ] [ 28313732 9816924 17035356 37% / ] [/dev/sda1 101086 27516 68351 29% /boot ] [tmpfs 2987896 0 2987896 0% /dev/shm ] [/dev/mapper/VolGroupPROD-ExportHome ] [ 15481840 3495504 11199904 24% /export/h +ome ] [/dev/mapper/VolGroupPROD-Production ] [ 15481840 1523692 13171716 11% /producti +on ] [/dev/mapper/VolGroupPROD-ProdLog ] [ 30963708 20410952 8979892 70% /producti +on/log ] [/dev/mapper/VolGroupPROD-ProdArchive ] [ 10313016 1693640 8095500 18% /producti +on/archive ] %devices (C:\Steve\Perl/debug.pm:887(990)): PREDEBUG (testdf3.pl:20): $line = '/dev/mapper/VolGroup00-LogVol00 ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [(undef)] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroup00-LogVol00] [size] => [(undef)] [used] => [(undef)] PREDEBUG (testdf3.pl:38): $percentage = '' PREDEBUG (testdf3.pl:41): $percentage = '' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroup00-LogVol00] [size] => [(undef)] [used] => [(undef)] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x25b510)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroup00-LogVol00] [size] => [(undef)] [used] => [(undef)] PREDEBUG (testdf3.pl:20): $line = ' 28313732 9 +816924 17035356 37% / ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [37%] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] PREDEBUG (testdf3.pl:38): $percentage = '37%' PREDEBUG (testdf3.pl:41): $percentage = '37' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x25b510)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroup00-LogVol00] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] PREDEBUG (testdf3.pl:20): $line = '/dev/sda1 101086 + 27516 68351 29% /boot ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [29%] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] PREDEBUG (testdf3.pl:38): $percentage = '29%' PREDEBUG (testdf3.pl:41): $percentage = '29' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x25b510)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroup00-LogVol00] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] PREDEBUG (testdf3.pl:20): $line = 'tmpfs 2987896 + 0 2987896 0% /dev/shm ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0%] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] PREDEBUG (testdf3.pl:38): $percentage = '0%' PREDEBUG (testdf3.pl:41): $percentage = '0' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x25b510)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroup00-LogVol00] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] [/dev/shm] => [HASH(0x21e5b8)] [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] PREDEBUG (testdf3.pl:20): $line = '/dev/mapper/VolGroupPROD-ExportHom +e ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [(undef)] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ExportHome] [size] => [(undef)] [used] => [(undef)] PREDEBUG (testdf3.pl:38): $percentage = '' PREDEBUG (testdf3.pl:41): $percentage = '' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ExportHome] [size] => [(undef)] [used] => [(undef)] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x24e4638)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ExportHome] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] [/dev/shm] => [HASH(0x21e5b8)] [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] PREDEBUG (testdf3.pl:20): $line = ' 15481840 3 +495504 11199904 24% /export/home ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [24%] [free] => [11199904] [mount] => [/export/home] [name] => [] [size] => [15481840] [used] => [3495504] PREDEBUG (testdf3.pl:38): $percentage = '24%' PREDEBUG (testdf3.pl:41): $percentage = '24' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0.24] [free] => [11199904] [mount] => [/export/home] [name] => [] [size] => [15481840] [used] => [3495504] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x24e4638)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ExportHome] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] [/dev/shm] => [HASH(0x21e5b8)] [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] [/export/home] => [HASH(0x24e4800)] [capacity] => [0.24] [free] => [11199904] [mount] => [/export/home] [name] => [] [size] => [15481840] [used] => [3495504] PREDEBUG (testdf3.pl:20): $line = '/dev/mapper/VolGroupPROD-Productio +n ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [(undef)] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-Production] [size] => [(undef)] [used] => [(undef)] PREDEBUG (testdf3.pl:38): $percentage = '' PREDEBUG (testdf3.pl:41): $percentage = '' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-Production] [size] => [(undef)] [used] => [(undef)] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x24e4848)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-Production] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] [/dev/shm] => [HASH(0x21e5b8)] [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] [/export/home] => [HASH(0x24e4800)] [capacity] => [0.24] [free] => [11199904] [mount] => [/export/home] [name] => [] [size] => [15481840] [used] => [3495504] PREDEBUG (testdf3.pl:20): $line = ' 15481840 1 +523692 13171716 11% /production ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [11%] [free] => [13171716] [mount] => [/production] [name] => [] [size] => [15481840] [used] => [1523692] PREDEBUG (testdf3.pl:38): $percentage = '11%' PREDEBUG (testdf3.pl:41): $percentage = '11' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0.11] [free] => [13171716] [mount] => [/production] [name] => [] [size] => [15481840] [used] => [1523692] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x24e4848)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-Production] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] [/dev/shm] => [HASH(0x21e5b8)] [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] [/export/home] => [HASH(0x24e4800)] [capacity] => [0.24] [free] => [11199904] [mount] => [/export/home] [name] => [] [size] => [15481840] [used] => [3495504] [/production] => [HASH(0x25b510)] [capacity] => [0.11] [free] => [13171716] [mount] => [/production] [name] => [] [size] => [15481840] [used] => [1523692] PREDEBUG (testdf3.pl:20): $line = '/dev/mapper/VolGroupPROD-ProdLog ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [(undef)] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ProdLog] [size] => [(undef)] [used] => [(undef)] PREDEBUG (testdf3.pl:38): $percentage = '' PREDEBUG (testdf3.pl:41): $percentage = '' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ProdLog] [size] => [(undef)] [used] => [(undef)] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x24e4860)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ProdLog] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] [/dev/shm] => [HASH(0x21e5b8)] [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] [/export/home] => [HASH(0x24e4800)] [capacity] => [0.24] [free] => [11199904] [mount] => [/export/home] [name] => [] [size] => [15481840] [used] => [3495504] [/production] => [HASH(0x25b510)] [capacity] => [0.11] [free] => [13171716] [mount] => [/production] [name] => [] [size] => [15481840] [used] => [1523692] PREDEBUG (testdf3.pl:20): $line = ' 30963708 20 +410952 8979892 70% /production/log ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [70%] [free] => [8979892] [mount] => [/production/log] [name] => [] [size] => [30963708] [used] => [20410952] PREDEBUG (testdf3.pl:38): $percentage = '70%' PREDEBUG (testdf3.pl:41): $percentage = '70' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0.7] [free] => [8979892] [mount] => [/production/log] [name] => [] [size] => [30963708] [used] => [20410952] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x24e4860)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ProdLog] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] [/dev/shm] => [HASH(0x21e5b8)] [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] [/export/home] => [HASH(0x24e4800)] [capacity] => [0.24] [free] => [11199904] [mount] => [/export/home] [name] => [] [size] => [15481840] [used] => [3495504] [/production] => [HASH(0x25b510)] [capacity] => [0.11] [free] => [13171716] [mount] => [/production] [name] => [] [size] => [15481840] [used] => [1523692] [/production/log] => [HASH(0x24e4638)] [capacity] => [0.7] [free] => [8979892] [mount] => [/production/log] [name] => [] [size] => [30963708] [used] => [20410952] PREDEBUG (testdf3.pl:20): $line = '/dev/mapper/VolGroupPROD-ProdArchi +ve ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [(undef)] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ProdArchive] [size] => [(undef)] [used] => [(undef)] PREDEBUG (testdf3.pl:38): $percentage = '' PREDEBUG (testdf3.pl:41): $percentage = '' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ProdArchive] [size] => [(undef)] [used] => [(undef)] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x24e4a70)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ProdArchive] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] [/dev/shm] => [HASH(0x21e5b8)] [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] [/export/home] => [HASH(0x24e4800)] [capacity] => [0.24] [free] => [11199904] [mount] => [/export/home] [name] => [] [size] => [15481840] [used] => [3495504] [/production] => [HASH(0x25b510)] [capacity] => [0.11] [free] => [13171716] [mount] => [/production] [name] => [] [size] => [15481840] [used] => [1523692] [/production/log] => [HASH(0x24e4638)] [capacity] => [0.7] [free] => [8979892] [mount] => [/production/log] [name] => [] [size] => [30963708] [used] => [20410952] PREDEBUG (testdf3.pl:20): $line = ' 10313016 1 +693640 8095500 18% /production/archive ' %info (C:\Steve\Perl/debug.pm:887(990)): %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [18%] [free] => [8095500] [mount] => [/production/archive] [name] => [] [size] => [10313016] [used] => [1693640] PREDEBUG (testdf3.pl:38): $percentage = '18%' PREDEBUG (testdf3.pl:41): $percentage = '18' %info (C:\Steve\Perl/debug.pm:887(990)): [capacity] => [0.18] [free] => [8095500] [mount] => [/production/archive] [name] => [] [size] => [10313016] [used] => [1693640] %devices (C:\Steve\Perl/debug.pm:887(990)): [] => [HASH(0x24e4a70)] [capacity] => [0] [free] => [(undef)] [mount] => [(undef)] [name] => [/dev/mapper/VolGroupPROD-ProdArchive] [size] => [(undef)] [used] => [(undef)] [/] => [HASH(0x24e3e28)] [capacity] => [0.37] [free] => [17035356] [mount] => [/] [name] => [] [size] => [28313732] [used] => [9816924] [/boot] => [HASH(0x21e708)] [capacity] => [0.29] [free] => [68351] [mount] => [/boot] [name] => [/dev/sda1] [size] => [101086] [used] => [27516] [/dev/shm] => [HASH(0x21e5b8)] [capacity] => [0] [free] => [2987896] [mount] => [/dev/shm] [name] => [tmpfs] [size] => [2987896] [used] => [0] [/export/home] => [HASH(0x24e4800)] [capacity] => [0.24] [free] => [11199904] [mount] => [/export/home] [name] => [] [size] => [15481840] [used] => [3495504] [/production] => [HASH(0x25b510)] [capacity] => [0.11] [free] => [13171716] [mount] => [/production] [name] => [] [size] => [15481840] [used] => [1523692] [/production/archive] => [HASH(0x24e4848)] [capacity] => [0.18] [free] => [8095500] [mount] => [/production/archive] [name] => [] [size] => [10313016] [used] => [1693640] [/production/log] => [HASH(0x24e4638)] [capacity] => [0.7] [free] => [8979892] [mount] => [/production/log] [name] => [] [size] => [30963708] [used] => [20410952] 8979892 PREDEBUG (testdf3.pl:51): $info = 'HASH(0x24e4a70)' PREDEBUG (testdf3.pl:51): $info = 'HASH(0x24e4638)' PREDEBUG (testdf3.pl:55): Found $info->{capacity} to be > .10 /production/log is at 70% with 8979892K remaining. PREDEBUG (testdf3.pl:51): $info = 'HASH(0x24e3e28)' PREDEBUG (testdf3.pl:55): Found $info->{capacity} to be > .10 / is at 37% with 17035356K remaining. PREDEBUG (testdf3.pl:51): $info = 'HASH(0x21e708)' PREDEBUG (testdf3.pl:55): Found $info->{capacity} to be > .10 /boot is at 28% with 68351K remaining. PREDEBUG (testdf3.pl:51): $info = 'HASH(0x21e5b8)' PREDEBUG (testdf3.pl:51): $info = 'HASH(0x24e4800)' PREDEBUG (testdf3.pl:55): Found $info->{capacity} to be > .10 /export/home is at 24% with 11199904K remaining. PREDEBUG (testdf3.pl:51): $info = 'HASH(0x25b510)' PREDEBUG (testdf3.pl:55): Found $info->{capacity} to be > .10 /production is at 11% with 13171716K remaining. PREDEBUG (testdf3.pl:51): $info = 'HASH(0x24e4848)' PREDEBUG (testdf3.pl:55): Found $info->{capacity} to be > .10 /production/archive is at 18% with 8095500K remaining.

I then modified _percentage_to_decimal to include defensive coding:

# Change 12.3% to .123 sub _percentage_to_decimal { my $percentage = shift; if (!defined $percentage) { $percentage = 0; } $percentage =~ s{%}{}; return $percentage / 100; }

That reduced the errors a bit:

C:\Steve\Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef>testdf4.pl Use of uninitialized value $info{"mount"} in hash element at C:\Steve\ +Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef\testdf4.pl line 14. Use of uninitialized value $info{"mount"} in hash element at C:\Steve\ +Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef\testdf4.pl line 14. Use of uninitialized value $info{"mount"} in hash element at C:\Steve\ +Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef\testdf4.pl line 14. Use of uninitialized value $info{"mount"} in hash element at C:\Steve\ +Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef\testdf4.pl line 14. Use of uninitialized value $info{"mount"} in hash element at C:\Steve\ +Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef\testdf4.pl line 14. 8979892 /production/log is at 70% with 8979892K remaining. / is at 37% with 17035356K remaining. /boot is at 28% with 68351K remaining. /export/home is at 24% with 11199904K remaining. /production is at 11% with 13171716K remaining. /production/archive is at 18% with 8095500K remaining.

So I added a trap in the main loop:

if (!defined $info{mount}) { my $displayLine = $line; chomp $displayLine; print "\$info{mount} undefined when \$line = [$displayLine]\ +n"; } else { $devices{ $info{mount} } = \%info; }

Now, the only "errors" displayed are the ones from the trap:

C:\Steve\Dev\PerlMonks\P-2013-12-18@1604-Hash-Undef>testdf5.pl $info{mount} undefined when $line = [/dev/mapper/VolGroup00-LogVol00] $info{mount} undefined when $line = [/dev/mapper/VolGroupPROD-ExportHo +me] $info{mount} undefined when $line = [/dev/mapper/VolGroupPROD-Producti +on] $info{mount} undefined when $line = [/dev/mapper/VolGroupPROD-ProdLog] $info{mount} undefined when $line = [/dev/mapper/VolGroupPROD-ProdArch +ive] 8979892 /production/log is at 70% with 8979892K remaining. / is at 37% with 17035356K remaining. /production is at 11% with 13171716K remaining. /export/home is at 24% with 11199904K remaining. /production/archive is at 18% with 8095500K remaining. /boot is at 28% with 68351K remaining.

I should think at this point the resulting code would help you figure out how to get rid of your logic errors:

#!/usr/bin/perl use strict; use warnings; my @headers = qw(name size used free capacity mount); my @df = &readDFfile('test.dat'); shift @df; # get rid of the header my %devices; for my $line (@df) { my %info; @info{@headers} = split /\s+/, $line; # note the hash slice $info{capacity} = _percentage_to_decimal($info{capacity}); if (!defined $info{mount}) { my $displayLine = $line; chomp $displayLine; print "\$info{mount} undefined when \$line = [$displayLine]\ +n"; } else { $devices{ $info{mount} } = \%info; } } # Change 12.3% to .123 sub _percentage_to_decimal { my $percentage = shift; if (!defined $percentage) { $percentage = 0; } $percentage =~ s{%}{}; return $percentage / 100; } # Now the information for each device is in a hash of hashes. # Show how much space is free in device /dev/ad4s1e print $devices{"/production/log"}{free} ; print "\n"; for my $info (values %devices) { # Skip to the next device if its capacity is not over 60%. next unless $info->{capacity} > .10; # Print some info about each device printf "%s is at %d%% with %dK remaining.\n", $info->{mount}, $info->{capacity}*100, $info->{free}; } exit; sub readDFfile { my ($rdofnm, @arglst) = @_; if (!defined $rdofnm) { $rdofnm = ''; } # -----[ Was command, now reading from file for testing purposes +]-------------- # my @df = `df -k`; # --------------------------------------------------------------- +--------------- my @df = (); if (open RDOFIL, '<', $rdofnm) { @df = <RDOFIL>; close RDOFIL; } # --------------------------------------------------------------- +--------------- return @df; } __END__

Holler if you need any additional assistance.

Replies are listed 'Best First'.
Re^2: undefined hash elements
by MrTEE (Novice) on Dec 19, 2013 at 15:33 UTC

    thank you very much - I really like the term you use "defensive coding". that sums up just what I was trying to achive here. In my perl coding i want to develop more defensive coding parctices. This is alot of beef to chew on - it should keep me feed for days.

      This particular form of defensive programming is sometimes called "fortressing", meaning it tries to keep bad data from getting in. The reciprocal function is called, if memory serves, "dungeoning", which is trapping bad data where it can do no harm. I don't know if I can think of any examples of where that approach serves much use -- which probably means I don't know as much about it as I thought I did. :-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1067744]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-04-24 19:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found