The first line of Perl_CGI script, env perl vs perl only, how different?
Hi ! Everyone there ! How are you ?
Until recently I runs all of my Perl scripts as well as Perl_CGI scripts by starting the folowing salutation,
#! /usr/bin/perl -w
The script with this beginning runs well at BASH shell at (/home/mkido/bin) LINUX such as Fedora, Ubuntu, Rocky (Alma-derivative). However, almost right now I noticed some of Perl example around has the different first line as below,
#! /usr/bin/env perl
And it doesn't seem to run at HOME BASH shell (/home/mkido/bin) by simple way of executing it by-itself by the command line. Will someone explain me about what is this [env perl] stuff? Thank you so much.
Mitsuru Kido
The difference doesn't have anything to do with Perl; it's how unix-like operating systems interpret files that start with a shebang (#!).
The first part after the shebang is the pathname to the executable that will be called with the file as the argument. If your file starts with
then the OS will execute the /usr/bin/perl file and hand it your script... assuming there's a /usr/bin/perl file to execute (usually there is). It's the exact equivalent to typing /usr/bin/perl yourscript.pl at your command line.However, if your script starts with
the OS will execute the /usr/bin/env file and hand it your script. How is this different? Well, the difference is that /usr/bin/env looks at the rest of the first line and it searches for the command in your path. Let's say you have /usr/bin/perl, but it's a crappy perl 5.10 that was installed by your operating system, and you have perl 5.36 installed at /usr/local/bin/perl. Putting /usr/local/bin in your path earlier than /usr/bin isn't going to do any good if your scripts all start with (or if you run all your scripts from the command line with /usr/bin/perl yourscript.pl), because those scripts will execute using the crappy 5.10 that's available at /usr/bin/perl. By using #!/usr/bin/env perl, it's the same as invoking the perl yourscript.pl : the OS searches your path and uses the first perl executable it finds, whether that's the one you have installed at /usr/local/bin/perl, or $HOME/perl5/bin/perl, or $HOME/perl5/perlbrew/perls/perl-5.36.0/bin.You can read more about the env command at https://man7.org/linux/man-pages/man1/env.1.html
Also, the -w you see in the #!/usr/bin/perl -w is just passing the "enable warnings" flag to Perl. If you're using /usr/bin/env, you can do the same thing by putting
However, I dislike using command line switches to do things in shebang lines. Command line switches are good for one-liners, but if I'm writing a script anyway, I'm just going to do things in a more verbose, easier to read way. That's why all my perl scripts start with
More info on how to invoke Perl: https://perldoc.perl.org/perlrun
Avoiding doing things on the shebang line is a matter of coding style and therefore subjective.
There is a much more important reason to avoid
-w
, which is objective: it’s not at all the same thing asuse warnings
. Whereasuse warnings
applies to the rest of the current scope,-w
is completely global. Under-w
, any module loaded directly or indirectly will have warnings forced on it, even if the module itself does not turn on warnings – which nowadays almost certainly means it was written to run without warnings. Therefore-w
should no longer be used. At all.We have had
use warnings
since Perl 5.6 – in fact lexical warnings were one of the major changes in that version. 5.6 came out in 2000. The-w
switch is 1990s technology.Thanks, thanks Packy Anderson.
I am not perfect to understand what you say, but at least I am getting into it. It appears to me that the script starting with
#!/usr/bin/env perl
use strict;
use warnings;
is popular nowadays. So, I will follow this way to see what will happen. I will also study your links too. Thanks, thanks so much.
Hello! Aristotle, thanks for your comment. I will follow your opinion. Let me see. Thanks, thanks.
I've also seen this:
#!perl
And it seems to work like "#!/usr/bin/env perl" on Linux (i.e. $PATH is consulted), but it fails completely on macOS. Best avoided.