How to check if perl is Windows command? - perl

I would like to write a batch file to silently install Perl MSI. However, the server/PC may have Perl installed, the batch file's flow would be:
Check if Perl is installed.
If not installed, install it silently.
I know that the command perl-v reports Perl version if Perl is installed, but do not have idea how to check whether the perl command is executable on the server/PC by windows batch file.

Perhaps How do I get the application exit code from a Windows command line? and Redirect Windows cmd stdout and stderr to a single file might help you.
Run
perl -e1 2>NUL
if errorlevel 1 (
echo Perl is not installed
)
perl -e1 simply executes the Perl expression 1 as a one-liner which always is successful if Perl is installed. It produces no ouput at all, except it complains when Perl isn't found. That's why I redirected STDERR to NUL so you will not see any output, even not the error messages.
The if errorlevel 1 checks whether the returncode of the last command (perl -e1 in this case) was >=1. If Perl is installed and was executable then its returncode will be 0 (meaning success) and the if won't trigger.
You could also use perl -v but that produces output on STDOUT. In that case you would have to redirect both STDOUT and STDERR to NUL, like so: perl -v >NUL 2>&1.

>nul 2>nul where perl || echo not installed
this checks for perl without trying to run perl.
where prints to STDOUT if it finds the file/command in folders listed in %PATH% or prints to STDERR if it doesn't.

Related

How to execute perl file from shell script

I have a question about how to execute the perl file inside of a shell script
I have 2 files now, "test.sh" and "test.pl", here are example of my scripts
SHELL script
#!/bin/bash
perl FILEPATH/test.pl
......
PERL script
#!/usr/bin/perl
my $a = "hello"
sub saysomething
{
print $a;
}
.....
The way I call the shell script is : under the path of shell scripts, execute "./test.sh"
All mentioned above are working under the environment
GUN bash, version 4.2.24(1)-release (i686-pc-linux-gnu) + perl (v5.14.2)
But if I put those scripts on server (which I couldn't change the bash / perl version)
GNU bash, version 4.2.10(1)-release (x86_64-pc-linux-gnu) + perl (v5.12.4), I got the followign message:
FILEPATH/test.pl: line 2: my: command not found
Does anybody know how can I solve this problem?
BTW, if I execute the perl script individually (perl FILEPATH/FILENAME.pl), it works perfectly.
In order to execute a perl script by .sh script you dont need to use perl prefix, but only:
#!/bin/sh
/somewhere/perlScript.pl
It will work without problem.
This problem is at least two-fold. One, you have to have the location of Perl in your environment PATH. Two, the location of Perl may be different on different machines. One solution to both problems that I, and others, have used for years is to make use of a "magic header" of some sort at the top of Perl programs. The header identifies itself as a sh shell script and leverages the fact that /bin/sh exists in every version/flavor of Linux/UNIX. The header's job is to fortify the PATH with various possible Perl locations and then run the Perl script in place of itself (via exec). Here is a "Hello World" example:
1 #! /bin/sh --
2 eval '(exit $?0)' && eval 'PERL_BADLANG=x;PATH="/usr/bin:/bin:/usr/local/bin:$PATH";export PERL_BADLANG;: \
3 ;exec perl -x -S -- "$0" ${1+"$#"};#'if 0;
4 exec 'setenv PERL_BADLANG x;exec perl -x -S -- "$0" $argv:q;#'.q
5 #!/bin/perl -w
6 +($0=~/(.*)/s);do(index($1,"/")<0?"./$1":$1);die$#if$#;__END__+if 0;
7 # Above is magic header ... real Perl code begins here
8 use strict;
9 use warnings;
10 print "hello world!\n";
Note: I added line numbers just to make it clear where lines start and end.
First check where perl is installed on your system, e.g. which perl and use that location in the shebang line instead of /usr/bin/perl, if it is different.
If all other recommendations fail, check the first line of the script on the machine where it is not running properly by doing this: head -1 test.pl | xxd. Does the output show the last two bytes as 0d 0a? If so, you probably copied over the file via Windows and didn't do a dos2unix conversion.
"command not found" is an error emitted by the shell. You are trying to run your Perl script by the shell, not by Perl.

Using perl temporarily in a batch file

I would like to use perl in a batch file then exit perl and continue with the batch code. A small example I would like to achieve :
perl do something
echo hello
pause
If Perl is installed, there should be no problem:
perl -e "print $_ for 1 .. 10"
perl script.pl
You might need to specify the full path to perl and the script.pl.
#echo off
perl script.pl
echo hello
pause
or
#echo off
perl -e" ...code..."
echo hello
pause
Maybe I'm just reading it wrong but I interpretted the question as asking how to embed perl scripts directly into batch files.
Activeperl adds a bunch of these as .cmd files and there is a tool on cpan for creating them from your perl script.
I also found two examples from a quick search that seem to extend the idea a little. They allow you to put the code into the same file and run dos commands before and after the perl call, which is what I thought you were asking.
Here's one of the examples:
#rem = 'Perl, ccperl will read this as an array of assignment & skip this block
#CD /d "%~dp0"
#perl -s "%~nx0" %*
#FOR /L %%c in (4,-1,1) do #(TITLE %~nx0 - %%cs to close & ping -n 2 -w 1000 127.0.0.1 NUL)
#TITLE Press any key to close the window&ECHO.&GOTO:EOF
#rem ';
#perl script starts below here
print 'Hi there! DOS rocks!\n'
You can also do vice-versa. i.e. Call Batch commands from perl
my $cmd = 'some command';
if (system $cmd) {
print "Error: $? for command $cmd"
}
Save this perl script. This should do your job as well.

Executing perl code inside shell script using eval

I came across the following example. I tried to google but could not find much so I'm posting this question here.
What is the benefit of executing the perl script like this?
How can we make the shell script work like a "normal" shell script once we are through executing the perl code?
Here's the code:
#!/bin/ksh
#! -*- perl -*-
eval 'exec $PERLLOCATION/bin/perl -x $0 ${1+"$#"} ;'
if 0;
print "hello world\n";
# how can I make it behave like a "normal" shell script from this point onwards? What needs to be done?
# echo "hello world" ### this results in error
This idiom is described in the perlrun documentation.
The -x switch scans the whole file and ignores anything that appears before the first line that begins with #! and also contains the word perl.
It means that your system will run the script with the Perl interpreter whether you invoke the script with perl or with a shell command (sh/bash/ksh/etc.)
That is,
$ perl this_script
and
$ sh this_script
will both run the script with perl.
To address your second question, this idiom has just about nothing to do with combining shell script and Perl script in the same file. There are a few different ways to approach that problem, but maybe the most readable way is to write in shell script, but use the shell's heredoc notation to invoke perl code.
#!/bin/bash
# this is a bash script, but there is some Perl in here too
echo this line is printed from the shell
echo now let\'s run some Perl
perl <<EOF
# this is now perl script until we get to the EOF
print "This line is printed from Perl\n";
EOF
echo now this is from the shell script again
1. If you start a Perl script in the usual way:
#!/usr/bin/perl
print "hello world\n";
the #! line will only work if the Perl interpreter is actually installed under /usr/bin. The perl/ksh bilingual script you show is a tricky kluge to make the script work even if perl is installed somewhere else. For more information, see e.g. this.
2. You can't. When the shell process encounters the exec command, it terminates and hands control over to perl. (Technically, it executes perl in place of the shell, without creating a new process.) The only way to run more shell commands after that would be to launch a new shell.
It's way simpler than what's already been posted.
#!$PERLLOCATION/bin/perl
doesn't work because the shebang (#!) line is interpreted by the kernel (not the shell), and the kernel doesn't do variable interpolation.
The code invokes ksh to expand the environment variable and to launch the specified installation of Perl.

How do I redirect the output of Perl script executed from within another perl script to a file?

I am running a perl script via crontab and redircting its output to a file:
30 1 * * * /full/path/to/my_script.pl >> /full/path/to/my_log_file
Within my_script.pl, I'm executing several other perl scripts via the system() command:
#/usr/bin/env perl
system( "/full/path/to/another_script.pl" );
And within those scripts, I am using 'print' to write to STDOUT:
#/usr/bin/env perl
print "Standard output...\n";
It appears, however, that none of those child scripts' output is getting redirected to my_log_file- The only output I see there is that of the parent perl script. Am I missing something obvious? This is on a linux system.
Instead of system(), use qx:
print qx( "/full/path/to/another_script.pl" );
Hmmm, if using system() then STDOUT should end up back in your log.
Do you have an example?
My immediate thoughts go towards the system() call isn't actually running the other scripts - do you use a full path to the script? Remember cron wont have the same $PATH that your shell has, so may not find the scripts you are trying to run unless they have the full path.
You could also capture STDERR in your log:
30 1 * * * /my_script.pl 2>&1 >> my_log_file

How can I run a Perl script on Mac OS X?

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 ~/)