perl library path - linux

I need to retrieve the path where the perl libraries Statistics and Distributions are located. The path is necessary to run the script. I'm on a computer cluster. Can anyone help me?
Thanks

This answer assumes that the module is in fact installed, but not in a place that perl is looking for.
Generally, the Perl module Statistics::Distributions will be contained in a file called Statistics/Distributions.pm. On Linux and similar systems, one can search for these files quickly with the locate command:
locate Statistics/Distributions.pm
If it is installed, locate will spit out a line similar to
/opt/my_perl/lib/Statistics/Distributions.pm
You can then instruct the perl interpreter to look in this path, too, in various ways. One is to define the environment variable PERL5LIB, i.e. from bash:
prompt> PERL5LIB=/opt/my_perl/lib/ ./myscript.pl
Or you can use the perl -I switch:
prompt> perl -I/opt/my_perl/lib/ ./myscript.pl
Or you can modify the script to use lib; there is more than one way to do it ;-)

perldoc -m Your::Module - displays source of module
perldoc -l Your::Module - display path to library if it's installed and found in PERL5LIB, -I, #INC, etc.

If you mean you need the path of a module you're using in a program, that's stored in %INC:
$ perl -MLWP::Simple -le 'print $INC{"LWP/Simple.pm"}'
/usr/share/perl5/LWP/Simple.pm

"Can't locate XXX in #INC" usually indicates the module isn't installed. Have you installed Statistics::Distributions?
cpan Statistics::Distributions

I had the same trouble and it can be fixed both ways:
1) by running the command
perl -I/blabla/folder_your_module_is_installed/blib/lib/ ./script.pl
for dummies like me, it is important to note that the end of the path is lib/, not lib/Other_folder/. Because there are more folders after it.
2) inside the script you can write:
use lib 'blabla/folder_your_module_is_installed/blib/lib/';
save and run perl scripit.pl

Related

Using Bash environment variables from within a Perl script?

I am trying to run a Bash command from within my Perl program.
However Perl seems to be confusing my Bash $PWD environment variable as a Perl variable.
How can I make it just read it all as a string?
This is what I'm trying to run
my $path = /first/path;
`ln -s $path $PWD/second/path`
Those backticks runs the second line in Bash. Using System() produces the same problem.
Any ideas?
There are two queries here, on use of Bash variables and on running external commands.
There is the %ENV hash in Perl, with environment variables
perl -wE'say $ENV{PWD}'
However, you are often better off getting the equivalent within the script, as things may have a subtly different meaning for the script or change as the script runs.
More importantly, using shell commands exposes you to all kinds of potential problems with quoting, shell injection, and interpretation. For instance, the command you show is dangerous, as outlined in Charles Duffy comment. It is in principle better to use Perl's rich functionality. See for example
Executing system commands safely while coding in Perl
Using system commands in Perl instead of built in
libraries/functions [duplicate]
for a sober, and detailed, account of advantages.
In case you do need to run external commands, it is best to avoid the shell altogether, for example by using the multi-argument form of system. If you need the output of the command as well there are various modules in Perl that provide that. See links below.
If you also need to use the shell's capabilities, instead of quoting everything just right in order for the shell to receive what it needs better use a ready tool like String::ShellQuote.
Some examples:
How to use both pipes and prevent shell expansion in perl system function?
Perl is respecting '<' as a regular character rather an output redirection
How to pipe the content of a variable as STDIN in a qx{} statement in Perl?
Perl system command with multiple parameters output to file.
Note that qx operator (backticks) uses /bin/sh, which may or may not get relegated to Bash. So if you want Bash you need system('/bin/bash', '-c', $cmd), where $cmd need be built carefully to avoid problems. See the links with examples.
Here is a full example related to the objective behind the question.
Your program's working directory may be other than expected depending on how it's started. For one, it changes after chdir. I don't know your exact intent with PWD, but in Perl there are core Cwd::cwd and FindBin with $RealBin, for the current working directory and for the directory where the script resides (generally different things).
To create a symbolic link to $path, with the relative path following the current working directory
use warnings;
use strict;
use Cwd qw(cwd);
my $cwd = cwd;
my $path = '/first/path';
symlink($path, "$cwd/second/path") or die "Can't make a symlink: $!";
If the path is meant to be the script's location use $RealBin from FindBin instead of cwd.
Note that with symlink you cannot pass a directory instead of a link name. See this page.

Making perl scripts executable... can I do away with the preceding 'perl' statement?

This is a pretty simple one... I just want to make a perl script executable without the preceding perl command, and instead let the environment deduce the interpreter from the shebang line. Here is my sample script called test:
#!/usr/bin/perl
print "Hey there\n";
I then use chmod 775 test to make the script executable. If I use the command perl test, I get the output Hey there.
However, if I just type test, I get no output. What's the deal? Why isn't my shebang line making the environment realize this is perl? Can someone please help me?
Don't name your script test. This is a built-in command in most shells, so they don't go looking for an external program.
Also, to run a program in your current directory, you should type ./programname. It's generally a bad idea to have . in your $PATH, which would be necessary to execute it without the directory prefix.
To run something from the current directory you need to prefix "./" to tell it "this directory" ie ./testprogram.
If you type just test it will look in standard install directories like /bin. This is why when you run cp or rm it knows where the executable is.
As mentioned by others, naming scripts test is not allowed with most shells.

running a program in linux from perl

I want to run a program from perl by using system command(or any other ways ).
system("samtools");
I think it should pass this to shell but it complains ,Can't exec "samtools" file or directory does not exist , when I run it.I have tried many other different program for example
system("velveth");
and it works properly but not this one (samtools). Is any of you facing this problem before?
I am really puzzled.
You can give the full path to that file location.
example:
system( "/usr/bin/perl -de 1");
Try putting Linux command inside `` characters. Will work as well.
Did you modify $path for samtools in the current shell manually?
Since system starts a new sub-shell to run your command, you have to append search path for samtools yourself if doesn't exist in your .bashrc. Check it by:
perl -e 'system("echo \$PATH")'
and
echo $PATH
to see if there's any difference.

perl + perl script location under /etc/rc3.d with diff results

I need advice about the following:
option 1
I run the script /usr/local/bbp/api/bbpinstaller.pl from /var/tmp directory in my Linux machine and there are no problem
option 2
I create new script - script.pl under /var/tmp
and then I create link from /var/tmp/script.pl to /etc/rc3.d/S99script.pl ( by ln -s )
so S99script.pl is link to /var/tmp/script.pl
and script.pl execute the /usr/local/bbp/api/bbpinstaller.pl
more /etc/rc3.d/script.pl
#!/bin/bash
/usr/local/bbp/api/bbpinstaller.pl
.
.
.
my problem :
when the script bbpinstaller.pl run after reboot from /etc/rc3.d/S99script.pl then I get the following errors ( /usr/local/bbp/api/bbpinstaller.pl run from S99script.pl )
Can't locate Term/ReadKey.pm in #INC (#INC contains: /etc/bbp/shared /usr/perl5/5.8.4/lib/sun4-solaris- 64int /usr/perl5/5.8.4/lib /usr/perl5/site_perl/5.8.4/sun4-
solaris- 64int /usr/perl5/site_perl/5.8.4 /usr/perl5/site_perl /usr/perl5/vendor_perl/5.8.4/sun4- solaris-64int /usr/perl5/vendor_perl/5.8.4 /usr/perl5/vendor_perl
. ) at /usr/local/bbp/api/bbpinstaller.pl line 25.
BEGIN failed--compilation aborted at /usr/local/bbp/api/bbpinstaller.pl line 25.
in /usr/local/bbp/api/bbpinstaller.pl script , I have the following perl modules:
#################################
# Modules imported
#################################
use Config;
use Getopt::Long;
use File::Find;
use English;
use Sys::Hostname;
$File::Find::dont_use_nlink=1;
use lib "/etc/bbp/shared";
use Term::ReadKey qw(GetTerminalSize);
use Cwd 'abs_path';
require "bbp_globals.pl";
require "bbp_functions.pl";
the PATH of the file ReadKey.pm
/usr/local/lib/perl5/site_perl/5.8.7/sun4-solaris-thread-multi/Term/ReadKey.pm
please help me to understand . what the problem here ??? ( I not have allot experience with Perl )
/usr/local/ is used by local installs (i.e. it wasn't provided by the OS vendor). Then your shell is setup to run ($PATH) /usr/local/bin/perl (5.8.7) rather than /usr/local/bin/perl (5.8.4).
However the init scripts don't run with your shell settings - they use the system settings, which won't have /usr/local/bin in them - so they will use the OS provided perl - /usr/bin/perl which doesn't have this library (Term::ReadKey) installed.
(The .pl extension is normally for perl programs - I'd use .sh for bash/shell scripts)
When you run a script directly (that is, not specifying an interpreter first on the command-line), the kernel uses the hash-bang line (the first line) to work out which program to execute to interpret the script.
e.g. your shell script /etc/rc3.d/script.pl has a hash bang line of "#!/bin/bash", telling it to execute with /bin/bash.
/usr/local/bbp/api/bbpinstaller.pl will have a hash-bang line at its start, possibly something like: #!/usr/bin/env perl
This tells the kernel/shell to look at the PATH variable to find an interpreter; the same way it would find perl if you typed it on the command-line.
In order to fix your problem, either:
Install Term/ReadKey into the system perl.
Set your PATH in you shell script as MichaelN suggests.
Call the explicit perl instead of letting the kernel decide, as MichaelN also suggests.
Recode /usr/local/bbp/api/bbpinstaller.pl to not need Term/ReadKey
By default the os perl is /usr/bin/perl which has all its modules in /usr/perl5/site_perl/5.8.4 /usr/perl5/site_perl. Since running the script via rc3 uses root's standard path and standard lib, it won't find your custom perl in /usr/local/bin and thus won't find your site-lib in /usr/local/lib. So you need to modify your calling script "/etc/rc3.d/script.pl" which is a bash script (should probably be call script.sh but that's symantics) to include /usr/local/bin in the path, ie: export PATH=/usr/local/bin:${PATH}. That'll pre-append the /usr/local/bin to the front of the PATH and then your perl in /usr/local/bin will be called instead of /usr/bin/perl. So change the script.pl to:
#!/bin/bash
export PATH=/usr/local/bin:${PATH}
/usr/local/bbp/api/bbpinstaller.pl
or call your script with your perl.
#!/bin/bash
/usr/local/bin/perl /usr/local/bbp/api/bbpinstaller.pl
I'm totally keying off the work Douglas did in analyzing your issue, in order to provide the fix you asked for.
I would either:
In the RC shell script, set your PATH to run the right version of perl, and then call your Perl script.
Change the "shebang" line in your Perl script to use the right version of Perl.
Hope one of those helps!

Perl module or method to create DVD compliant ISO from directory without system commands

Are there any Perl modules or combination of modules to create DVD compliant ISOs? This will run on Linux and I'm not concerned about portability. What I'm looking to do is create a DVD compliant ISO from a directory that contains a VIDEO_TS directory structure. The solution would not need to rip an actual DVD.
What I currently run is:
genisoimage -V 'Name_of_DVD' -dvd-video -o dvd.iso /some_directory
I am aware of Perl ability to run external commands:
system function
exec function
backticks (``) operator
open function
There is also CPAN the CPAN module Filesys::MakeISO::Driver::Mkisofs which uses genisoimage/mkisofs. What I specifically want is a solution that does NOT use linux/OS commands. If there are no such solutions or the solution is overly complex then please state that. Thanks.
While I share the enthusiasm for CPAN, I think that if there isn't something obvious that works, and you don't care about portability away from linux, then I would just do
use strict;
use warnings;
use autodie;
...
system( q# genisoimage -V 'Name_of_DVD' -dvd-video -o dvd.iso /some_directory # );
or as you mention, use Filesys::MakeISO::Driver::Mkisofs.
Not trying to be snarky, but CPAN is supposed to be productivity++, but if it doesn't exist, then do what works.

Resources