wrapper script and GetOpts::Long perl - perl

I have been trying to make GetOpts :: Long work for my code but it just doesn't respond. I have a wrapper script with about 8 scripts and 2 commands. I have been trying to GetOpts :: Long submit arguments into the separate codes, but it doesnt work!
For example, I've script 1 though 8, and on the command line I'm trying to a few options that I would like to submit to the separate scripts. When I use the GetOpts module in the seprate scripts and run them separately, they run fine. But when I try to run the wrapper script, say wrapper.pl which initiates script 1 with the module being called in it; the arguments submitted are not being taken by the separate scripts.
Please help!!!!
I hope this sort of explains the problem. wrapper script looks like this(wrapper.pl),using backticks:
perl script1.pl;
perl script2.pl; (etc)
script1.pl uses the GetOpts::Long option for the input file. script1.pl calls for the input file using the "-i" option, but the file is not being read when initiated on the command line.
command line option: perl wrapper.pl -i seqs.fa -o op.fa

Do you actually pass in the arguments from your wrapper.pl into the
scripts ? - how would they magically know what options they need to
handle?
vanHoesel asked the right questions; you have to do something like that in wrapper.pl:
use Getopt::Long;
GetOptions('i=s' => \$input_file,
'o=s' => \$output_file) || die "Usage: $0 -i INPUT -o OUTPUT\n";
`perl script1.pl -i $input_file`;
`perl script2.pl -o $output_file`;

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.

from cron running a subroutine from a perl module

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?

Output of bash script in perl script

I want to embed a bash script inside a perl script. I want to run my bash script by taking some variables from the perl script. Once it gets the variable the bash script takes over and tries to output the files that is created within.
How can I pass the perl script variable to my bash script ?
I do not know perl but from what I read in Google, I can embed my bash script as
system("get_files.cmd -yr ${year}");
where my bash script is get_files.cmd.
I think it might be better if you passed them as arguments to your bash script.
The perl call:
system("get_files.cmd ${var1} ${var2}");
The bash script
var1="$1"
var2="$2"
...
Where $1, $2 are the arguments passed in the command line (in order). Note that you can use the $# bash variable to get the number of arguments passed.
Hope this helps =)
The Expect module can essentially automate shell tasks such as running scripts and passing perl variables. Such that:
Use Expect;
# create an Expect object by spawning another process
my $exp = Expect->spawn($command, #params)
or die "Cannot spawn $command: $!\n";
http://search.cpan.org/~rgiersig/Expect-1.15/Expect.pod

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 can I call a Perl function from a shell script?

I have written a library in Perl that contains a certain function, that returns information about a server as a character string. Can I call this function from a shell directly?
My boss asks "Can you call it from a shell directly for the time being?" Because he said that, I think I should be able to do it, but how do I do it?
perl -MServerlib=server_information -e 'print server_information()'
Is another way to do this, but only if Serverlib exports server_information sub. If it doesn't, you would need to do the below instead:
perl -MServerlib -e 'print MServerlib::server_information()'
As perl's command line arguments are a bit inscrutable, I'd wrap it in a simpler perl script that calls the function. For example, create a script serverinfo which contains:
#!/usr/bin/perl
require 'library.pl';
say library::getServerInformation();
then run:
chmod u+x serverinfo
The advantage of doing it this way is the output and arguments of the script can be corrected if the function itself changes. A command line script like this can be thought of as an API, which shouldn't change when the implementation changes.