Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Configuration File

by crackotter (Beadle)
on Jul 15, 2003 at 00:21 UTC ( [id://274237]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks,
I am having a problem finding a efficient way of using a configuration file for my script.
Here is a example:
##Router Identification router router1 = 192.168.1.2 router router2 = 192.168.1.3 router router3 = 192.168.1.4 router router4 = 192.168.1.5 router router5 = 192.168.1.6 ##Set up groups group1 = router1,router5 group2 = router1, router2, router3 group3 = router2, router3, router4
This would be stored in a configuration (text) file, lets say it is called "router.conf".
I want to load the router section into a hash.
I want to load each to which group to load, and whichever group I load, I want it to be a list or a hash.
Should I be using AppConfig??? If so how??
Thank You,
<TAB>Otter

Replies are listed 'Best First'.
Re: Configuration File
by legLess (Hermit) on Jul 15, 2003 at 03:47 UTC

    Use YAML! YAML is a simple, human-readable data-serialization format. It can round-trip any Perl data structure (that anything else can parse, anyway -- nothing's perfect) with no loss, doesn't require evals, and is very easy to work with.

    One thing YAML's implementors had in mind at the start was to make a better syntax for config files. YAML's brutally simple in this regard:

    # snippet my $data = "anything you want"; DumpFile( "/path/to/file", $data ); my $newdata = LoadFile( "/path/to/file" ); # now $data == $newdata

    The code below is long, but that's mostly data. It dumps the data twice with Data::Dumper, before and after a YAML read/write cycle, just to prove they're the same. Lastly is the data as represented by YAML - very clean and easy to read.

    #!/usr/bin/perl use strict; use warnings; use YAML qw/ LoadFile DumpFile Dump /; use Data::Dumper; local $Data::Dumper::Indent = 1; use constant DIV => '-' x 20 . "\n"; my $routers = { 'routers' => { 'router1' => '192.168.1.2', 'router2' => '192.168.1.3', 'router3' => '192.168.1.4', 'router4' => '192.168.1.5', 'router5' => '192.168.1.6', } }; my $groups = { 'groups' => { 'group1' => [ 'router1', 'router5', ], 'group2' => [ 'router1', 'router2', 'router3', ], 'group3' => [ 'router2', 'router3', 'router4', ] } }; print "Dumping initial data...\n" . DIV; print Dumper $routers, $groups; print "Writing YAML file...\n"; DumpFile( "./yaml-test.conf", $routers, $groups ); print "Reading YAML file...\n"; ( $routers, $groups ) = LoadFile( "yaml-test.conf" ); print "Dumping YAML'd data...\n" . DIV; print Dumper $routers, $groups; print "Dumping YAML'd data with YAML...\n" . DIV; print Dump $routers, $groups;
    And here's the output:
    Dumping initial data... -------------------- $VAR1 = { 'routers' => { 'router5' => '192.168.1.6', 'router1' => '192.168.1.2', 'router3' => '192.168.1.4', 'router4' => '192.168.1.5', 'router2' => '192.168.1.3' } }; $VAR2 = { 'groups' => { 'group2' => [ 'router1', 'router2', 'router3' ], 'group1' => [ 'router1', 'router5' ], 'group3' => [ 'router2', 'router3', 'router4' ] } }; Writing YAML file... Reading YAML file... Dumping YAML'd data... -------------------- $VAR1 = { 'routers' => { 'router5' => '192.168.1.6', 'router1' => '192.168.1.2', 'router3' => '192.168.1.4', 'router4' => '192.168.1.5', 'router2' => '192.168.1.3' } }; $VAR2 = { 'groups' => { 'group2' => [ 'router1', 'router2', 'router3' ], 'group1' => [ 'router1', 'router5' ], 'group3' => [ 'router2', 'router3', 'router4' ] } }; Dumping YAML'd data with YAML... -------------------- --- #YAML:1.0 routers: router1: 192.168.1.2 router2: 192.168.1.3 router3: 192.168.1.4 router4: 192.168.1.5 router5: 192.168.1.6 --- #YAML:1.0 groups: group1: - router1 - router5 group2: - router1 - router2 - router3 group3: - router2 - router3 - router4

    --
    man with no legs, inc.
Re: Configuration File
by nite_man (Deacon) on Jul 15, 2003 at 08:44 UTC
    Try to look at Config::Tiny. Config file can look like this:
    debug = 1 [routers] router1 = 192.168.1.2 router2 = 192.168.1.3 router3 = 192.168.1.4 router4 = 192.168.1.5 router5 = 192.168.1.6 [groups] group1 = [router1,router5] group2 = [router1, router2, router3] group3 = [router2, router3, router4]
    You can get access to the those variables in your script:
    use Config::Tiny; my $conf = Config::Tiny->read('your_config'); my $debug = $conf->{_}->{debug}; my $routers = $conf->{routers}; # Hash ref with routers information my $groups = $conf->{groups}; # Hash ref with group information my $router1 = $routers->{router1}; # Router's IP my $group1 = $groups->{group1}; # Array ref with routers list which be +long to group 1. . . .
    Hope I helped :)
          
    --------------------------------
    SV* sv_bless(SV* sv, HV* stash);
    
Re: Configuration File
by tcf22 (Priest) on Jul 15, 2003 at 01:17 UTC
    I think this is what you might be looking for:
    #! /usr/bin/perl use strict; use Data::Dumper; my (%routers); #Load Router list while(<DATA>){ last if( m/##GROUPS/ ); chomp; my($name, $ip) = (split(/ /, $_))[1,3]; $routers{$name} = $ip; } my $group = 'group2'; #Get group to load here my (%loaded_routers); #Load requested group while(<DATA>){ chomp; s/ //g; #Clear spaces my($groupname, $data) = split(/=/, $_); if($groupname eq $group){ foreach my $n(split(/\,/,$data)){ $loaded_routers{$n} = $routers{$n}; } last; } } print Dumper \%loaded_routers; __DATA__ router router1 = 192.168.1.2 router router2 = 192.168.1.3 router router3 = 192.168.1.4 router router4 = 192.168.1.5 router router5 = 192.168.1.6 ##GROUPS group1 = router1,router5 group2 = router1, router2, router3 group3 = router2, router3, router4

    The Output:
    $VAR1 = { 'router1' => '192.168.1.2', 'router3' => '192.168.1.4', 'router2' => '192.168.1.3' };

    Update: AppConfig looks like a viable option as well. The above will work on the sample data that you gave, but AppConfig is much more robust, and would probably be better it the data gets anymore complicated.
Re: Configuration File
by Cody Pendant (Prior) on Jul 15, 2003 at 03:13 UTC
    This seems like exactly the kind of file that the docs for XML::Simple talk about.

    “Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.”
    M-J D

      Hi there,

      I deeply dislike XML for configuration files. Unless your configuration data is extremely complicated, with deeply nested environments, you don't need XML at all; and if so, why are you using such a complex configuration anyway?

      A simple win INI style config file is powerful enough to give a lot of structure to a config file, and still easily human readable and editable (see Chris Winters' 'Why I love INI files', his lightning talk this year at YAPC) .

      I'm with legLess that YAML is a great option for configuration files.

      A different approach that I have successfully used in the past is having a flat key: value(s) file, and provide a module (called Foo::RC.pm) to give it structure by the means of functions (get_router_data(), get_groups_data(), etc...). This has the added advantage of putting all the code (open file, chomp, split, etc...) in one, authoritative place, well documented and maintained, and the ability to merge different configuration files/formats if your system is complex enough that any subsystem just needs a special format for itself. It also makes it more robust before ill-formed config files (all sanity check again performed in just one place) and easily extendable.

      As a project meets new requirements during it's development/life time, as it's bound to happen, anyway, your DTD would have to be enhanced to reflect the new functionality, this justs ask for a lot of front-desk thinking about a design you don't yet know. I don't like it at all.

      best regards,

      --
      our $Perl6 is Fantastic;

        I deeply dislike XML for configuration files. Unless your configuration data is extremely complicated, with deeply nested environments, you don't need XML at all; and if so, why are you using such a complex configuration anyway?

        XML files are complicated if YOU make it complicated. Imho, it's the best way to make a portable config file. Parser for xml exists for almost every language. And it is also much fessibile. Change from a simple configuration to a more complex one is a joke with xml. I can't say the same thing for the ini files.

        ----------
        kral
        (sorry for my english)
        I just want to say, "in my defense" so to speak, that I don't look after any servers and don't use any config files of this type, I was simply pointing out that the specific example documented in the XML::Simple POD was this kind of file, as far as I could see.

        In fact the description of XML::Simple is "Easy API to maintain XML (esp config files)".



        “Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.”
        M-J D

      I don't think you can rule out XML that easily. It is simple to implement, and provides more scaleability and flexibilty for the future, IMHO.

      If you decided you needed to create a more complex config file, for instance having nested groups or the like, it would involve less coding and work to make the change.

      Also, if you decided that you wanted to be able to access this file via an api, through another application, or through the web, it gives you a standardized format to work with.

      </ajdelore>

Re: Configuration File
by crackotter (Beadle) on Jul 15, 2003 at 00:26 UTC
    My mistake, I meant in the group section I want to choose which of the groups to load (will only load one of the variables based on user input). None of the other 'group variables will be loaded.
Re: Configuration File
by tzz (Monk) on Jul 15, 2003 at 13:31 UTC
    # read the AppConfig docs! use AppConfig qw/:expand :argcount/; my $config = AppConfig->new(); # note that variable names are case-insensitive by default $config->define( 'ROUTER'=> { ARGCOUNT => ARGCOUNT_HASH }, 'GROUP1' => { ARGCOUNT => ARGCOUNT_LIST }, 'GROUP2' => { ARGCOUNT => ARGCOUNT_LIST }, 'GROUP3' => { ARGCOUNT => ARGCOUNT_LIST }, ); $config->file('router.conf'); # now you can access the data # (untested, but this should give you the idea) printf ("Router %s is %s\n", $_, $config->ROUTER()->{$_}) foreach keys %{$config->ROUTER()}; printf ("Group %s is %s\n", $_, @{$config->get($_)}) foreach qw/group1 group2 group3/;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://274237]
Approved by Thelonius
Front-paged by tcf22
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2024-04-19 02:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found