Running Perl scripts from a file in linux - perl

I'm in Linux (CentOS) trying to run a basic Perl script from a file. I am getting an error. I think it has something to do with the syntax, but I can't figure it out.
$ perl -e 'print "Hello World\n";'
This runs fine and will print Hello World on the next line. However, when I put this into vi and save it as perlOne, exactly the same (perl -e 'print "Hello World\n";') and run the command:
$ perl perlOne
I get the error: "syntax error at perlOne line 1, near "perl -e -- Execution of perlOne aborted due to compilation errors."
It's the same line, but it does not work in the file.
I'm working through the Perl tutorial from Linux Pro Magazine - which is where I got this from.

The command-line switch -e allows you to run code from the command line, instead of having to write your program to a file and then execute it.
$ perl -e 'print "Hello World\n";'
Output:
Hello World
If you want to run it from your file you will need to write it differently:
#!/usr/bin/perl
use strict;
use warnings;
my $message = 'Hello World';
print $message . "\n";
# You can also make it directly
print "Hello World\n";
While I do not recommend it can also be written as:
print "Hello World\n";

Related

Perl runtime bug in OGS HPC cluster

I'm attempting to debug a HPC cluster.
One problem: submitting Perl scripts into a several hundred node Linux Suse cluster via Open Grid Scheduler (OGS/GE 2011.11).
This generates a runtime error for Perl scripts on the "long queue" in the cluster, but not on the "short queue".
$> qsub -cwd -q short.q ./test.pl
Output is ok
$> qsub -cwd -q long.q ./test.pl
Output error log,
/var/spool/sge/comp26/job_scripts/3141815: line 2: syntax error near unexpected token my'
/var/spool/sge/comp26/job_scripts/3141815: line 2:open (my $fh, '>', 'test.out');'
If I submit a shell script to the long queue it works, containing
perl ./test.pl
Any ideas?
System: GNU bash, version 4.2.46(2), Perl v5.16.3 (yuk)
Test script
#!/usr/bin/perl
# Also tried #!/bin/perl
system("perl -v > perl.out");
open (my $fh, '>', 'test.out');
print $fh 'test';
close $fh;
The solution,as #bytepusher described, was
#!/usr/bin/env perl
and submission to qsub -cwd -q long.q ./test.pl was fine.

How to call a Perl program from a csh script

I have this simple code to execute, but have failed.
a.csh
#! /bin/csh -f
`perl a.pl`
a.pl
#use perl
eval 'exec perl -w -S $0 ${1+"$#"}'
if 0;
use Cwd;
print "here.\n";
When I run a.csh, it reports an error as below.
here: Command not found
I am not sure what that means; any suggestion is welcome.
The backticks in your program are returning the output of the perl script. Then csh tries to execute that output as csh. toolic's comment telling you to remove the backticks is correct: perl a.pl. Reading more about how backticks work might be useful.

Conditional Perl Shebang?

I have a situation where I need to detect if a particular perl executable, /usr/goofy/bin/perl exists and if so use it to run the Perl script otherwise use /usr/bin/perl.
I have been struggling with this small POC script, called perlshebang.pl:
#!/bin/sh -e
perls="/usr/goofy/bin/perl /usr/bin/perl"
for pl_exec in $perls
do
if [ -x $pl_exec ]; then
exec "$pl_exec -w -S \"$0\" ${1+\"$#\"}"
fi
done
print "[$^X] Whoop!\n";
When I run this on a system that does not have /usr/goofy/bin/perl I get this error message:
./perlshebang.pl: 6: exec: /usr/bin/perl -w -S "./perlshebang.pl" : not found
And when I run it on a system that does have /usr/goofy/bin/perl I get a similuar error message:
./perlshebang.pl: line 6: /usr/goofy/bin/perl -w -S "./perlshebang.pl" : No such file or directory
I think I am close but cannot figure out why I am getting these error messages.
Thanks!
To answer your question, "Why am I getting these error messages?", the problem is your exec line:
exec "/path/to/cmd arg arg"
# This will attempt to execute a file named "cmd arg arg"
# (with spaces in name) in directory /path/to/
Contrast that with
exec /path/to/cmd arg arg
# This will attempt to execute a file named "cmd" in directory
# /path/to/, with arguments "arg" and "arg"
So, that is why the shell complains that it cannot find your executable. You don't have a file named perl -w -s "perlshebang.pl", neither under /usr/bin/ nor under /usr/goofy/bin/.
This sounds a little ugly to me if you are releasing software that uses this hack
If you have no other choice, then I suggest you make sure there is always a /usr/goofy/bin/perl, and use the shebang line
#!/usr/goofy/bin/perl
on all your scripts.
For those systems where you want to use the system perl, just make /usr/goofy/bin/perl a symlink to /usr/bin/perl
A co-worker of mine came up with this. I am not sure I fully understand it but it seems to work fine:
#!/bin/sh
#! -*-perl-*-
eval ' if test -x /usr/goofy/bin/perl ; then
exec /usr/goofy/bin/perl -x -S $0 ${1+"$#"};
elif test -x /usr/bin/perl ; then
exec /usr/bin/perl -x -S $0 ${1+"$#"};
fi '
if $running_under_some_shell;
use strict;
use warnings;
print "hello world\n"; # if $foo;
printf("running %s v(%vd)\n", $^X, $^V);
__END__
unpod like docs.
See http://perldoc.perl.org/perlrun.html
You can run the idea out of a Perl script running /usr/bin/perl. Use the shebang line with the 'goofy perl' in your script that should run. Then run the following wrapper, followed by the normal invocation of the script (its name and arguments).
#!/usr/bin/perl
exec "#ARGV";
exec "/usr/bin/perl #ARGV";
print STDERR "Couldn't execute either.\n";
Let's call the above pick_perl.pl, and your script is script.pl. Run it all as
pick_perl.pl script.pl args-for-script
The exec replaces the running program altogether with the one it executes, ie. it loads the new program. Thus your script runs with its own shebang. If that failes exec returns quietly (with false) and the next statement is executed so the other Perl runs the script (overriding the shebang). This happens if script's shebang fails, but also if the first exec fails to execute for any reason.
If you wish/need to run checks then put exec in a full if block. One can also interrogate the 'goofy_perl' file further if -e isn't assuring enough.
#!/usr/bin/perl
$system_perl = "/usr/bin/perl";
$goofy_perl = "/usr/goofy/bin/perl";
# Your 'goofy_perl' script with its arguments
#script_cmd = #ARGV;
if (-x $goofy_perl) { exec "#script_cmd" }
exec "$system_perl #script_cmd";
The #script_cmd has the full command line for your script (which has 'goofy_perl' shebang).

Access perl module within Bash script

I have a perl module with data definitions (hashes, arrays, etc.), is there any way I can access that data from inside a bash script? This isn't working for me...
#!/bin/bash
perl -e 'use Data'
tests=`perl -e "#tests"; `
echo "Perl tests = ${tests}" # prints "Perl tests = "
The module looks something like this:
our #EXPORT_OK = qw( #tests );
our #tests = qw( 1 2 3 4 5 );
If you have package variable #tests inside Data module,
perl -MData -e 'print "$_\n" for #Data::tests'
For perl 5.10 and above,
perl -MData -E 'say for #Data::tests'
You can use a module from the command line with -M
perl -MData -e'print map {"$_\n"} #tests;'
In the code you give, you run one interpreter that loads Data. It exits. You then run a second interpreter, which prints #tests. As that's the only action the second interpreter has performed, it's uninitialized, and prints nothing.

executing perl code from commandline in windows

i am very new to perl just began to learn when i try to assign a scalar a value and the print it i am facing problem. I am doing
perl -e "$number=30;"
perl -e "print $number;"
the output doesnt show anything but when i do
perl -e "$number=30; print $number;"
the output shows 30 why?
This:
perl -e "$number=30;"
runs the Perl program $number=30;, which sets the variable $number to 30 and then does nothing with it.
This:
perl -e "print $number;"
runs the Perl program print $number;, which prints the value of the uninitialized variable $number.
The key point is that, since these are two completely separate Perl programs, there's no connection between the variable $number in the first program and the variable $number in the second program. There is no relationship between the two programs, and no communication between them, so they do not and cannot share any variables.
when you execute:
perl -e "$number=30;"
perl -e "print $number;"
these are two independent processes, so they don't share information. Variable $number won't be available to the second command.
The other one:
perl -e "$number=30; print $number;"
Works because it runs in the same execution, and $number is visible to the next print sentence