I have perl scripts starting with #!/usr/bin/perl or #!/usr/bin/env perl
First, what does the second version mean?
Second, I use Ubuntu. All the scripts are set as executables. When I try to run a script by simply invoking it's name (e.g. ./script.pl) I get : No such file or directory. when I invoke by perl ./script.pl it runs fine.
Why?
The #!/usr/bin/env perl uses the standard POSIX tool env to work around the "problem" that UNIX doesn't support relative paths in shebang lines (AFAIK). The env tool can be used to start a program (in this case perl) after modifying environment variables. In this case, no variables are modified and env then searches the PATH for Perl and runs it. Thus a script with that particular shebang line will work even when Perl is not installed in /usr/bin but in some other path (which must be in the PATH variable).
Then, you problem with ./script.pl not working: you said it has the executable bit(s) set, like with chmod +x script.pl ? But does it also start with a shebang (#!) line ? That is, the very first two bytes must be #! and it must be followed by a file path (to perl). That is necessary to tell the kernel with which program to run this script. If you have done so, is the path correct ? You want to try the #!/usr/bin/env perl variant ;-)
Using #!/usr/bin/env perl gets around the problem of perl not necessarily being in /usr/bin on every system; it's just there to make the script more portable
On a related note, for your second problem, is there a /usr/bin/perl and/or /usr/bin/env? If not, that would explain why running the scripts directly doesn't work; the shebang isn't handled if you run the script as an argument to perl
Related
I have a Perl Module that i created and i want to run one of the subroutine in it on a schedule. I know I can just make a small perl script that calls the subroutine and call it from the crontab but if there is a way to call the subroutine right from the crontab that would be cool!
Is this possible?
You can use Perl's -e switch for executing code from the command line, e.g.
perl -e 'use your_module; your_function()'
Make that even shorter with the -M switch for loading a module:
perl -Myour_module -e 'your_function()'
The perlrun man page is your friend.
You can run the subroutine from the command line using something like
perl -MYour::Module=some,functions,to,import,such,as,foo -e 'foo();'
So you will be able to do the same from the crontab. Note that the cron usually runs with a restricted set of environment variables, so you may need to add a -I/path/to/your/modules option.
If you want a more elegant solution, your module can be configured to detect that it is being run as a script and behave differently in that situation. See this discussion: In Perl, how can I find out if my file is being used as a module or run as a script?
I was looking through my CPAN distributions and realized that I had various inconsistent things at the top of my .t scripts, based on where I'd cargo-culted them from. This of course offends me.
So, what's the "best" first line of a Perl test (.t) script? A non-scientific survey of my .cpanm sources showed me:
3429 use strict;
3211 #!/usr/bin/perl
1344 #!/usr/bin/env perl
937 #!perl
909 #!/usr/bin/perl -w
801 #!perl -w
596
539 #!perl -T
Related to What should I use for a Perl script's shebang line?, but here I'm wondering if the shebang is necessary/useful at all, if tests are always expected to be called from prove.
use strict; should be in EVERY Perl program (as well as use warnings; and probably a few others (depending who you talk to). It doesn't have to be the first line.
The rest of the stuff you present are merely multiple versions of the shebang. On Unix and Unix based systems, the shebang is used to tell the interpreter to use. If the shebang isn't there, the current shell will be used. (That is, if your shell supports the shebang1.).
If you are on a Windows system, that shebang line is useless. Windows uses the suffix of the file to figure out how to execute the file.
The question is whether you really even need a shebang line in scripts that you run through a test harness. I don't normally execute these test scripts individually, so there may not really be a need for the shebang at all. In the rare event you do want to execute one of these scripts, you could always run them as an argument to the perl command itself. The same is true with Perl modules.
So, why the shebang? Mainly habit. I put one too on my test scripts and on my modules. If nothing else, it makes it easy to run modules and test scripts independently for testing purposes. Plus, the shebang lets people know this is a Perl script and not a shell script or a Python script.
There's a little issue with the shebang though, and that has to do with portability. If I put #! /usr/bin/perl on my first line, and the Perl interpreter is in #! /usr/local/bin/perl, I'll get an error. Thus, many of the shebangs reflect the location of the Perl interpreter for that developer.
There's also another issue: I use Perlbrew which allows me to install multiple versions of Perl. The version of Perl I currently have in my shell is at /Users/David/perl5/perlbrew/perls/perl-5.18.0/bin/perl. That's not good if I pass that program to another user on another system. Or, if I decide I want to test my Perl script under 5.10.
The #! perl variant is an attempt to solve this. On SunOS (I believe), this would execute the Perl that's in your $PATH (since it could be /usr/local/bin/perl or /usr/share/bin/perl or /usr/bin/perl depending upon the system). However, this does not work on most Unix boxes. For example, on my Mac, I would get a bad interpreter error.
I use #! /usr/bin/env perl. The env program takes the argument perl, sees where perl is on my $PATH, and then executes the full path of wherever Perl happens to be on my $PATH. This is the most universal way to do the shebang and the way I recommend. It allows those of use to use Perlbrew without problem.
Note, I said almost universal, and not universal. On almost all systems, env is located in /usr/bin, but there apparently some systems out there where env is either on /bin, located elsewhere, or not on the system at all.
The -w turns on warnings when executing Perl. Before Perl 5.6, you used this to turn on warnings. After Perl 5.6, you can use the more flexible use warnings; and the -w is now considered deprecated2. Programs may use it because they were originally written pre 5.6, and never modified or the developer simply did it out of habit.
The -T has to do with taint mode. Taint mode is normally used for CGI scripting. Basically, in Taint mode, data from outside a program is considered tainted and cannot be used until untainted. Taint mode also affects #INC and PERLLIB.
The real answer is that there is no set answer. I'd put #! /usr/bin/env perl as my first line out of habit -- even if I never expect to execute that file from a Unix command line. There's no real need for it for these types of scripts that are almost always executed as part of the install and not directly from the command line. What you see is really the result of 30 years of Perl habits and cruft.
1. Your shell supports the shebang unless you're using a 30 year old version of the Bourne shell or a very old version of the C shell.
2. I actually don't know if -w has ever been officially deprecated, but there's no reason to use it.
.t files are still regular Perl script. Use whatever you need for this particular script on first line.
I used to delete my ActivePerl once, and all the installed modules were lost. So now I am very careful with this kind of issue. Due to some reason, I want to use Strawberry Perl now, while keeping ActiveState's ActivePerl in use.
Will this cause compatibility issues? Is it advisable?
This will not be a problem as both the Perl implementations will look at different directories for modules. That is, the #INC entries will be different.
I keep both ActivePerl and Strawberry Perl installed on my Windows 7 Pro instance. My PATH variable order decides my Perl preference. E.g, for using ActivePerl I set my PATH to something like this:
C:\Perl64\bin;C:\strawberry\perl\bin
You can always override this in your script using shebang:
#!C:\strawberry\perl\bin\perl
You could use two (many) different Perl versions at once.
Set your PATH variable to include your primary Perl path (path to perl.exe) to be sure that you are running the correct Perl when you start a program with perl script.pl.
You could use Perlbrew (or other modules) to help keeping multiple Perl installations on your computer.
It is available on Windows: http://code.activestate.com/ppm/App-perlbrew/
I found another solution for this. You could embed your Perl code into a Windows batch file. This way you could set environment variables before executing your Perl script or include your module path.
#echo off
cd %TEMP%
set perl_bindir=C:\strawberry\perl\bin
set module_dir=C:\my_perl_modules
set path=%perl_bindir%;%path%
echo Launching %0 perl script
%perl_bindir%\perl.exe -I %module_dir% -x -S %0 %*
goto endofperl
#!perl -w
use strict;
print "Hello World\n";
__END__
:endofperl
How do I run a Perl script on OS X?
You can run your Perl script by invoking the Perl interpreter and giving your file as input:
perl myprogram.pl
The easiest way to run a perl script is with the option:
perl myprogram.pl
However, you may find it more useful to add a shebang line at the top of the perl file.
#!/usr/bin/perl
print "Hello World!\n";
In order to execute this script, you need to add execute permissions to your program. Run:
chmod +x myprogram.pl
Now, in order to run your script, you can simply type:
./myprogram.pl
A good tutorial on Perl in OSX can be found here:
http://www.mactech.com/articles/mactech/Vol.18/18.09/PerlforMacOSX/index.html
A generic documentation on executing Perl code is of course perldoc perlrun.
To answer your question directly:
You can run a perl script on any Unix system by either having the code evaluated and executed from command line:
perl -e 'print "Hello World\n"';
Or you can save your Perl script to a file (customarily having .pl extension, say script1.pl and with the first line being #!/usr/bin/perl) and then you can execute it as any Unix program (after setting proper execute permissions)
/path/to/script/script1.pl
You can also execute a script from a file by running perl interpreter as the command and giving the script as a parameter (in this case execute permissions to the script are not needed):
perl /path/to/script/script1.pl
For some reason the whole directory didn't work for me but I just did
perl ~/Desktop/file.pl
(you could also use any folder that is in your user-folder after the ~/)
I have Strawberry Perl and have msys Perl 5.6 removed.
Now perl will invoke Strawberry (due to PATH env) but how do I map the perl command in .pl or other Perl script files which have #!/bin/perl or #!/usr/bin/perl shebang lines?
I was thinking of making a hardlink to perl.exe in msys/bin or merge the whole Strawberry inside the msys directory, but I'm not sure.
The solution is to create a symlink to the Strawberry Perl executable from within MSYS Tip of the hat to smaudet for his input:
First, remove or rename the Perl executables that the MSYS installation came with, if any (which the OP has already done); e.g.:
mv /usr/bin/perl /usr/bin/perl.msys
mv /usr/bin/cpan /usr/bin/cpan.msys
Then create a symlink to Strawberry Perl's executable in its place:
ln -s /c/strawberry/perl/bin/perl.exe /usr/bin/perl
# Unfortunately, doing the same for `cpan` doesn't work directly, because
# Strawberry Perl's `cpan` executable is a *batch* file, `cpan.bat`, which
# cannot be directly invoked from MSYS.
# To invoke it from MSYS (assuming it is in the %PATH%):
# cmd /c 'cpan.bat ...'
# With an explicit path:
# cmd /c 'c:\strawberry\perl\bin\cpan.bat ...'
#
# Here's how to create a stub script that still allows invocation as
# `cpan`:
echo 'cmd /c "C:\strawberry\perl\bin\cpan.bat $*"'>/usr/bin/cpan && chmod +x /usr/bin/cpan
Once the /usr/bin/perl symlink is in place, existing scripts with shebang lines #!/usr/bin/perl and #!/bin/perl will work again (the latter also works, because /bin and /usr/bin are effectively the same location in MSYS).
Note that scripts written with the more flexible shebang line #!/usr/bin/env perl do not need this, because env will directly find Strawberry Perl's perl.exe in the path.
Some background:
Unix-emulation environments such as MSYS and Cygwin do not respect Windows' %PATHEXT% variable to determine what executable to invoke a (non-binary) file with. In other words: filename extensions have no meaning with respect to execution there.
Instead, they solely go by whether the file has a shebang line:
If there is one, the executable specified in the shebang line is used.
If there is none, the default (POSIX-like) shell /bin/sh is used.
Thus, trying to invoke *.bat or *.cmd files directly fails, because they don't have a Unix shebang line and are therefore executed by /bin/sh rather than cmd.exe.
Unlike in Windows, this also works with (executable) files that have no filename extension at all.
this works beautifully on the windows side of the computer, on the MSYS side you may need to
check the PATH environment variable and fix to include the strawberry perl access path
check the scripts for complete path in the shebang line (#!/usr/bin/perl).
Those paths that are absolute in msys are in fact relative to the msys install directory in windows.
you may need to "plug" your strawberry perl install to match or change the #! line
in the latter case my recommendation would be to use something like: #!env perl that checks the environment for the perl interpreter and alleviate the burden of dealing with /cygdrive/c/my/windows/path/not/visible/from/msys/otherwise
The correct shebang would be, eg. #!"C:/strawberry/perl/bin/perl.exe". However, you might prefer to run scripts explicitly with Perl rather than rely on the shebang, eg. perl script.pl or perl "C:\strawberry\perl\bin\cpan"
Note that Strawberry Perl doesn't get the shebang right for its own scripts, such as cpan and perldoc . Bug reported at https://rt.cpan.org/Public/Bug/Display.html?id=82837