t:
#!/usr/bin/perl
exec("perl -Ilib -d" . $ARGV[0]);
It's invoked as t perl_script.
But after that I can't find it by ps,and can't terminate it by ^C
What's wrong ?
http://perldoc.perl.org/functions/exec.html
You're exec'ing perl with the args and perl_script you pass in. This means the current script t ceases to exist and is replaced by perl -Ilib -dperl_script.
The process you're looking for with ps will be the one you passed in (perl_script)
Edit for comment from OP below:
The actual process is perl since that's what you exec'd, but you can certainly find it via the perl_script you passed in using grep:
$ ps -ef |grep perl_script
broach 13039 2264 0 01:08 pts/0 00:00:00 perl -Ilib -dperl_script
Do you need to include a space after -d? Otherwise you are exec'ing
perl -Ilib -dperl_script
instead of
perl -Ilib -d perl_script
Cleaner still:
exec("perl","-Ilib","-d",$ARGV[0]);
exec($^X, "-Ilib", "-d", $ARGV[0]);
Related
perl -e 'print(123, #ARGV);' a b
# 123ab
perl -e 'print(123, #ARGV);' --help
# prints Perl's help instead
This is a toy example demonstrating the problem. In my real use-case I'm using -e to execute a large script from an embedded interpreter using perl_parse(...) function, the script has its own processing of --help switch, so I'd like to block any special processing of command line arguments after -e.
Is it possible?
Use a double hyphen to stop argument processing:
$ perl -e'print "[#ARGV]\n"' -- --help
[--help]
$
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).
I'm traying to get the output of netcat as a perl script argument in linux :) , here is my perl code: while(1){ if(#ARGV>1){some traitement ....}
in the terminal I tested this: netcat -l -u -p 1111 | perl myscript.pl
and this is not working, I'm receiving data I can check it on wireshark.
but this data need to be redirected to myscript.pl as parameter. if it is possible to do it with .sh file it will be ok.
thank you.
You're passing the output to perl's STDIN. You can simply do the following to read it:
while (<>) {
...
}
If you really need the output as a parameter, use the following (but keep in mind there are limits on the size of parameters):
perl myscript.pl "$( netcat ... )"
use xargs like this (older/different netcat program called nc)
nc -l 1111 | xargs perl -e '$!=1;print #ARGV'
At the other end of the socket send an EOF. Once this happens all the parameters are passed to the script
I tried to list all the subroutines of a script with the perl debugger and put the results in an external file. But It didn't work.
My code:
perl -d -S myscript.pl > results.txt
-S = list all subroutines
-d = debug perl script
Greets,
The -S isn't supposed to be used as a command line switch. Running perl -d will start a debugger process, and one of the commands you can use there is S.
Example:
$ perl -d tmp/splithttpdconf.pl
Loading DB routines from perl5db.pl version 1.28
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(tmp/splithttpdconf.pl:6): my $basedir = shift;
DB<1> S main::
main::BEGIN
main::debug
main::splitconf
DB<2>
In order to get the kind of output you want, you can to use the profiler module Devel::DProf instead. It'll output profiler info into a file which can be read by the dprofpp program. Here's an example to get the list of subroutines:
perl -d:DProf perlscript.pl; dprofpp -T
If you only want the subroutines within your own script, and not those loaded from other modules, add a grep to it, e.g.:
perl -d:DProf perlscript.pl; dprofpp -T | grep main::
Though for the particular question of knowing what subroutines exist in a given program, provided you use a consistent coding style it'd probably be easier to just do a grep "sub.*{" to start with.
In your home directory, create a file called .perldb with the following contents:
parse_options("NonStop=1 LineInfo=results.txt AutoTrace=1 frame=2");
And then run the command
perl -d myscript.pl
If you want to scan and list the entire subroutine's what Perl see's before it runs:
perl -MO=Deparse -f myscript.pl
Hi would like to pass a parameter to my perl script that should be executed trough qsub.
So I run:
qsub -l nodes=node01 -v "i=500" Test.pl
While in Test.pl I try to call i parameter in several way:
use Getopt::Long;
$result = GetOptions ("i" => \$num);
open(FILE,">/data/home/FILEout.txt");
print FILE "$num\n";
print FILE "$ARGV[0]";
close(FILE);
Unfortunatelly output file of the perl script is always empty.
Do you have any suggestions? Where I'm wrong? Help please
According to all documentation I can find -v sets an environment var, so you'd use $ENV{i} to get 500. (Check your own documentation to confirm.)
If you wanted to actually pass an arg to your script, you could try using
qsub ... Test.pl -i=500
But based on my web search, that might only work for some versions of qsub. Others would require that you make a helper script (say Test.sh)
#!/bin/sh
Test.pl "-i=$i"
along with the command
qsub ... -v 'i=500' Test.sh
If qsub ... Test.pl ...args... is supported and you can change your script, the simplest solution is
qsub ... Test.pl 500
and
my ($i) = #ARGV;
I Finally get the solution that works with PBRProfessional 10.4.
There are two way to solve it:
First one is the following
echo "perl /path/to/Test.pl -i 500" | qsub -l nodes=node06
Second one is two use
qsub -l nodes=node06 -v i=500 Test.pl
and read the parameter in the Test.pl through $ENV{i}