Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

.env loading the dot env file?

by szabgab (Priest)
on Mar 28, 2021 at 08:52 UTC ( [id://11130500]=perlquestion: print w/replies, xml ) Need Help??

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

I have seen the .env file mentioned in several applications and environments, but my search-foo fails me and I could not find an explanation if using .env files is a standard or what?

In any case I was wondering if any Perl-related modules or system automatically load the content of the .env file and add the values from them to %ENV? Is there maybe a module that just by being used would do this? Basically this code:

use strict; use warnings; my $filename = '.env'; if (-e $filename) { open my $fh, '<', $filename or die "Could not open '$filename' $!" +; while (my $line = <$fh>) { next if $line =~ /^\s*(#.*)?$/; chomp $line; my ($key, $value) = split /\s*=\s*/, $line; $ENV{$key} = $value; } } # and just to display: for my $key (sort keys %ENV) { printf("%-26s %s\n", $key, substr($ENV{$key}, 0, 40)); }

Replies are listed 'Best First'.
Re: .env loading the dot env file?
by arpad.szasz (Pilgrim) on Mar 28, 2021 at 17:36 UTC
      This seems to be exactly the thing I was looking for.
Re: .env loading the dot env file?
by Corion (Patriarch) on Mar 28, 2021 at 09:08 UTC

    See Get default login environment and the discussion therein. There is Shell::EnvImporter.

    I'm not sure if you really want the effects of a shell script, or just something that "looks like sh environment commands". If so, your approach seems good, but doesn't respect quoted constructs.

    In your code, I would at least change the split() to a more robust parser, so that it also understands foo=bar=baz as setting foo to bar=baz:

    #my ($key, $value) = split /\s*=\s*/, $line; if( $line =~ /^\s*([^=]+)=(.*?)\s*$/ ) { my ($key,$value) = ($1,$2); $ENV{$key} = $value; } else { croak "Malformed environment line: '$line'"; };

    Support for foo="bar=baz" and foo=\"bar=baz\" would also be addable, but if you want to support multiline values, you'll have to switch away from line-based parsing.

    Updated: The capturing parentheses were missing for the key, spotted by Anomalous Monk

      I think in the cases I saw this, the .env file was more like an INI file without any sections and certainly without any shell-like executions. Just plain key-value pairs. I am not sure even quotes are needed. However splitting to only 2 values should be used so the value part could contain an equal sign as well. Better yet, use your suggestion.

      I am still wondering how much is this a "standard practice" or a good practice?

        It is definitely not "best practice" to parse config files of any format that is not your own in an ad hoc way. It's a last resource if you can't figure out the format or proper way to use it for affecting your environment externally to your Perl program; that said, if you have to do it you have to do it. Try not to, though.
Re: .env loading the dot env file?
by hippo (Bishop) on Mar 28, 2021 at 09:32 UTC

    It depends how complicated/rigorous you want to make it. I would probably start from Config::General as with features like -InterPolateEnv and -AllowMultiOptions you can get much of the functionality and configurability built-in.

    I have seen the .env file mentioned in several applications and environments

    It might be helpful to know which ones. Just a thought.


    🦛

Re: .env loading the dot env file?
by Haarg (Priest) on Mar 28, 2021 at 15:54 UTC

    As far as a standard goes: I've investigated parsers for the "dotenv" format in other languages, and I'm pretty sure no two of them had compatible parsing. Possibly the rust parser was strict enough that it would either parse the same as a shell, or fail to parse.

    I have a module about 80% done that would parse all of the variants I found, and allow editing the files without losing order or comments. But of course the last 20% takes too much effort and I haven't found the motivation to complete it.

Re: .env loading the dot env file?
by LanX (Saint) on Mar 28, 2021 at 18:41 UTC
      Very nice. The benefit here is that you don't have to do anything externally when invoking your script. Thank you and bookmarked :)
        Yes I like this inside-out approach too, since it's trivial to share data between different languages. :)

        BUT I should add that source has the same limitation like a do config.pl ... it's evaling code which might pose a bigger security problem than only "parsing" the file.

        OTOH that's also the case if the shell does it, before executing Perl.

        It wasn't clear to me what kind of .env the OP wants. And %ENV is always security relevant.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Re: .env loading the dot env file? -- module
by Discipulus (Canon) on Mar 28, 2021 at 12:44 UTC
    Hello szabgab,

    just once we play vice versa: I write and you read ;)

    I dont know this being a standard, nor I know if it is wise.. but why dont use directly perl instead?

    Adapting my Modules as configuration files you can have ( in modconfenv.pm ):

    use strict; use warnings; $ENV{XX} = 42; $ENV{YY} = 'whatever you wont'; unshift @ARGV,$_ for reverse map {s/\s*#.*$|^\s*#.*$//; (split ' ',$_,2)} split /\n/, <<'EOCONF' --put here your --list of arguments and #any #indented --comment #comments --too EOCONF ; print "@ARGV" unless caller; 1;

    and then just perl -Mmodconfenv -e "print qq($ENV{XX} $ENV{YY})"

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: .env loading the dot env file?
by perlfan (Vicar) on Mar 28, 2021 at 18:32 UTC
    .env is not standard in any traditional shell I am aware of, but that set is limited to: sh/bash and csh/tcsh.

    If the format of that file indicates a standard shell "rc" type file with (for Bourne style), then I would not attempt to read it in your Perl program since it can contain anything the shell supports. The following is deceptive because it's just a basic shell script:

    VAR="some value" export VAR

    Rather, source it before your Perl program is invoked. This will do the right thing, and be available in %ENV.

    If it's an ini format, use something like Config::Tiny - or whatever module is appropriate for the serialization format. Because that's all it is; don't invent your own. you would not do this for JSON, YAML, or XML - I hope :)

    A few notes about understanding the %ENV in your Perl program; and assuming we're dealing strictly within the same process space on the same machine, etc:

    • your entire environment is available to a perl process under which it is invoked via %ENV
    • modifying %ENV in your program is respected by the current process and all child processes created by it (including via system, fork etc
    • child processes can affect their own env and that of their ancestors descendants, but not of their parent - even if you export - this means when your program returns from running to your interactive shell (e.g.,) the environment will not have changed based on anything your program did (and it can't)
    • best practice is to localize %ENV if you plan on mucking with it in your perl program, e.g., local %ENV = %ENV; - this is so you can control the scope of the changes in the same process using Perl's built in scoping; in other words, it allows you to "go back" to the original %ENV or at least only affect it in very precise parts of your program; as noted above, it is not needed to "protect" your interactive shell's environment once the program has returned

    The last thing I'll end with is, don't parse files that are meant to affect your shell environment in Perl. Use the shell to source it; then invoke your program. HTH

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11130500]
Approved by Corion
Front-paged by haukex
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-03-29 13:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found