wishartz has asked for the wisdom of the Perl Monks concerning the following question:
Dear Monks, I'm trying to create a program that runs a 'du' command on a file system and prints to a file the people who are using the most space.
There is just one part that I am having a problem with and that is, one host could have more than one file system. So, the hash key of host would have more than one value. Do I need to use a hash of array's?
The program will take one argument and that is the file system. What I want to do is if that file system is not on the host that the program is running on, it will display an error.
I've tried to use this, but it doesn't work.
our %filesystems = (
1 => {
host => "hosta => 1",
description => "filesysa",
filesystem => { \/file\/system\/a => \/file\/system\/b => 1
+},
},
2 => {
host=> "hostb => 2",
description => "file sys c)",
filesystem => { \/file\/system\/c => 2 },
},
);
host=`hostname`;
Can anybody help?
Re: Mulitple values for a key in a hash
by jettero (Monsignor) on Nov 29, 2007 at 14:41 UTC
|
Hash keys are strings. You can get away with {key=>2} if and only if the key doesn't have strange symbols in it. I bet you need filesystem => { "/file/system/a" => 1, "/file/system/b" => 2 } or something like that.
You also have to keep things balanced... { key1 => key2 => 3 } probalby doesn't mean what you think. It's actually { key1 => 'key2', 3=>undef }.
Also, what doesn't work?
| [reply] [d/l] [select] |
|
Thank's for the help. What I meant by it doesn't work, is there was something worng with the syntax and it was generating an error when I ran it.
I would like to run the script with an argument being the file system. That part I can do, by saving the contents of ARGV[0] into the variable $filesystem. I would then like to check that the file system is served by the host that the program is running on. If it isn't report an error. for example:
$host = `hostname`;
$filesystem = $ARGV[0];
Now I would like to check those details against my hash. That is the part that is confusing me. One host could have multiple filesystems. How would I go about looking up whether the file system belongs to the host, or not?
Thanks
| [reply] |
Re: Mulitple values for a key in a hash
by tcf03 (Deacon) on Nov 29, 2007 at 14:50 UTC
|
my %filesystems = ( hosta => { desc => 'x', filesystem => [ qq|/a/b/c
+/d/e/f| ] },
hostb => ( desc => 'r', filesystem => [ qq/w/e/r /
+home ] } );
Thats how I would write the structure. Although, just a suggestion, I would use an ini file or some sort of config file to hold the host info and build %filesystems with code.
Ive used Config::INI::Reader for such things ( ini files ) and it works well.
Ted
--
"That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
--Ralph Waldo Emerson
| [reply] [d/l] |
Re: Mulitple values for a key in a hash
by sh1tn (Priest) on Nov 29, 2007 at 15:03 UTC
|
perldsc tutorial will help you understand Perl data structures, especially HoH (HASHES OF HASHES).
| [reply] |
|
I read about the hash of hashes and tried the following. Although, the check doesn't seem to work, it prints error when the condition should be false. Does anybody know where I'm going wrong?
$filesystem = $ARGV[0]; #store the file system you would like to run D
+U command on
if ( $ARGV[0] eq "" ) {
die "usage: $0 filename\n";
}
$host=`hostname`;
my %filesystems = (
hosta => { desc => 'x', filesystemA => [ q
+q|/the/first/filesystem|], filesystemB => [ qq|/the/second/fielsyste
+m| ] },
hostb => { desc => 'r', filesystemA => [ q
+q|/the/first/filesystem | ], filesystemB => [qq|no filesystemB for 2n
+d host |]}
);
$choice = $filesystems{$host};
if ( not $filesystems{filesystemA}{$filesystem} ) {
print "error\n";
}
| [reply] [d/l] |
|
#!/usr/bin/perl -w #added
use strict; #added
use Data::Dumper #added
my $host = $ARGV[0]; #update was 'hosta';
my $fsys = $ARGV[1]; #update was qq|/the/second/filesystem|;
my %filesystems = (
hosta => { #update
desc => 'x',
filesystems => { #update
qq|/the/first/filesystem| => 0,
qq|/the/second/filesystem| => 0
} #update
}, #update
hostb => { #update
desc => 'r',
filesystems => { #update
qq|/the/first/filesystem| => 0,
qq|no filesystemB for 2nd host | => 0
} #update
} #update
);
print Dumper(\%filesystems); #added
if ( ! exists $filesystems{$host}{filesystems}{$fsys} ) {
print "error\n";
}
else {
print "Found filesystem $fsys on host $host\n"
. $filesystems{$host}{descr} . "\n";
}
Note: Untested!
...roboticus
Update: You'll notice that this node has been edited heavily. I've added some lines (suitably marked), included Data::Dumper (which is how I found my goofs). The error was that I used parenthesis () instead of curlies {} in my hash declarations. | [reply] [d/l] |
|
|
|
|
In case that you need hash key existance (and not only) check use exists.
my %filesystems = (
hosta => { desc => 'x', filesystemA => qq|/the/first/filesystem|,
+filesystemB => qq|/the/second/fielsystem| },
hostb => { desc => 'r', filesystemA => qq|/the/first/filesystem|, f
+ilesystemB => qq|no filesystemB for 2nd host|}
);
print "filesystemA exists\n"
if exists $filesystems{'hosta'}->{'filesystemA'};
print "no_such_fs does not exist\n"
if not exists $filesystems{'hosta'}->{'no_such_fs'};
| [reply] [d/l] |
|
|
Re: Mulitple values for a key in a hash
by gamache (Friar) on Nov 29, 2007 at 14:45 UTC
|
Perhaps you could either form the hash key out of the hostname and filesystem, something like 'host1:/foo', 'host1:/bar', 'host2:/baz' etc, or you could key by hostname and have each value be a hashref keyed by filesystem.
I don't fully understand what you're doing, however, based on your code sample... There are a number of problems I can see at first glance:
- "hosta => 1" is a string; did you want it to be a hashref? Same with "hostb => 2".
- Avoid barewords like \/file\/system\/a; put in single quotes instead, like '/file/system/a'.
- You try to put a hashref in $filesystems{1}{filesystem}, but it has an odd number of elements. Hashes and hashrefs should contain only key => value pairs.
- You need a $ sigil on host in the last line.
| [reply] [d/l] [select] |
|
|