I was looking at the source code for the CPAN Perl module Digest::Perl::MD5 and noticed that it has the she bang #! /usr/bin/false. Here's the first few lines of Digest/Perl/MD5.pm ...
#! /usr/bin/false
#
# $Id: MD5.pm,v 1.19 2004/02/14 02:25:32 lackas Exp $
#
package Digest::Perl::MD5;
use strict;
use integer;
use Exporter;
use vars qw($VERSION #ISA #EXPORTER #EXPORT_OK);
... why would the author of Digest::Perl::MD5 use #! /usr/bin/false? And what if my system does not have /usr/bin/false but has /bin/false instead?
why would the author of Digest::Perl::MD5 use #! /usr/bin/false?
So that if someone tried to use the module as an executable (Perl $ ./MD5.pm), it would quietly die instead of trying to execute the module as a program.
And what if my system does not have /usr/bin/false but has /bin/false instead?
Then it will nosily die complaining that it couldn't find /usr/bin/false if anyone tried that.
Related
I have made my own perl modules(pm files),named test.pm
package test;
use Exporter;
use strict;
use File::Basename qw(basename dirname);
use Cwd qw(abs_path);
use File::Path qw(make_path);
use FindBin qw($Bin $Script);
BEGIN {
our #ISA = qw(Exporter);
our #EXPORT = qw(mkdirOrDie);
our $VERSION = 1.0;
}
sub mkdirOrDie
{
my ($dir) = #_ ;
if(!-d $dir){
make_path($dir);
$dir=abs_path($dir);
# timeLog("Directory Created: $dir");
}
}
and I tried to install this module as follows,
h2xs -AX -n test
perl Makefile.PL
make
make install
there is no error,and I copy the test.pm to /usr/lib64/perl5/5.10.0/,but when i call sub function using test, an error has occurred,
Undefined subroutine &main::mkdirOrDie called at /to/my/path/main.pl line 92
is there something i ignored?
It's unclear at which point things started to go wrong for you.
Firstly, test.pm is a bad name for a Perl module. Perl modules should have names that begin with upper case letters (and Test.pm is already taken).
You should run h2xs before writing your code - as it generates a module skeleton for you fill in. I hope it hasn't overwritten your code with an almost empty file! It's also worth noting that most people stopped using h2xs many years ago. These days we have tools like Module::Starter.
Then, running, make install (which you need to do with root permissions - so usually with sudo) is what installs your module into the system libraries. There should be no need to run that cp command afterwards.
As for why your code doesn't find the module, there are many possible reasons. Are you using Perl 5.10 or do you have other Perl versions installed? What does the code look like that you are trying to use? Does test.pm still include the code you think it does?
Need more information to be much help here.
module.pm
package module;
use 5.012;
use warnings;
sub Parse
{
return 1;
}
1;
script.pl
#!/usr/bin/perl -w
use 5.012;
use warnings;
use lib 'C:/';
use module;
print Parse("value");
Stdout
Undefined subroutine &main::Parse
You need either to write:
print module::Parse("value");
or to change the module package to export the name Parse.
See http://perldoc.perl.org/perlmod.html#Perl-Modules for guidance in exporting symbols from your module.
(By the way, you should really name your module Module rather than module. Lowercase module-names are used for Perl built-in features like use warnings and use strict.)
Several things:
First, use Local as your module prefix. That way, if you just happen to have a module with the same name in your Perl installation, it will use yours. Call it "Local::Module". Then, create a Local directory, and name your module Module.pm.
The other thing you have to understand is that you define your module in another namespace. By default, everything is in the main namespace until you use the package statement. That creates another namespace that your package uses. This way, if your package has a function foo, and you've defined a function foo in your main program, they won't collide.
Thus, you have two choices: One (the preferred now) is to simply call your subroutine with the full package name prepended to it. The second is to export your subroutine names to your main program. This can cause problems with duplicate names, but you don't have to keep typing in the package name every time you call your subroutine.
Without Exporting the name
Local/Module.pm
# /usr/bin/env perl
# Local/Module.pm
package Local::Module;
use strict;
use warnings;
sub Parse {
my $value = shift; #Might as well get it.
print "I got a value of $value\n";
return $value;
}
1; #Need this or the module won't load
program.pl
# /usr/bin/env perl
# program.pl
use strict;
use warnings;
use Local::Module;
Local::Module::Parse("Foo");
With export:
Local/Module.pm
# /usr/bin/env perl
# Local/Module.pm
package Local::Module;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK(Parse); #Allows you to export this name into your main program
sub Parse {
my $value = shift; #Might as well get it.
print "I got a value of $value\n";
return $value;
}
1; #Need this or the module won't load
program.pl
# /usr/bin/env perl
# program.pl
use strict;
use warnings;
use Local::Module qw(Parse);
Parse("Foo");
I have two perl modules where one is the "object base" and the other imports functions from this "object base" module. When I compile the second module (perl -c Foo/Bar/NewObject.pm) it compiles without any warnings.
The issue is if I include the UNIVERSAL module in compiling the second module (perl -MUNIVERSAL -Mstrict -wc Foo/Bar/NewObject.pm) it throws warnings like:
"set" is not exported by the Foo::Bar::Object module
So my question is why does including UNIVERSAL cause the Exporter function to fail exporting symbols from the 'object base' model?
An example of what the modules look like are below.
object base:
#!/usr/bin/perl -w
use strict;
package Foo::Bar::Object;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw( new set get update create );
...
1;
second module:
#!/usr/bin/perl -w
use strict;
package Foo::Bar::NewObject;
use Foo::Bar::Object qw( new set get );
...
1;
I ended up resolving this by follow what #ikegami linked in the comments. I had to wrap the #EXPORT in a BEGIN {} block and that seemed to work.
There must have been a module trying to use the methods before they were exported.
My scripts are getting too long. How do I split my code (procedural subs) into multiple Perl files and tell the interpreter to make sense of them?
Kind of like:
# -> main.pl
#include "foo.pl"
say_hello();
and:
# -> foo.pl
sub say_hello {print "hello!"}
What you want to do is create one or more modules. Start by looking over perlmod, especially the Perl Modules section.
Since you say you're writing procedural code, you'll want to export functions from your modules. The traditional way to do that is to use Exporter (which comes with Perl), although Sub::Exporter is a newer CPAN module that allows for some nice things. (See also its Sub::Exporter::Tutorial for an introduction to exporting functions.)
Modules can be placed in any of the directories listed in the #INC variable. Try perl -V to get a list. You can also use lib to add directories at runtime. One trick is to use the FindBin module to find the location of your script, and then add a directory relative to that:
use FindBin; # Suppose my script is /home/foo/bin/main.pl
use lib "$FindBin::Bin/lib"; # Add /home/foo/bin/lib to search path
Your sample code, converted to a module:
In main.pl:
#! /usr/bin/perl
use strict;
use warnings;
use Foo;
say_hello();
In Foo.pm:
package Foo;
use strict;
use warnings;
use Exporter 'import';
our $VERSION = '1.00';
our #EXPORT = qw(say_hello);
sub say_hello {print "hello!"}
1; # A module must end with a true value or "use" will report an error
I think you may be looking for do? http://perldoc.perl.org/functions/do.html
put it in the same folder as your class and add use ClassName to the top of the calling file.
Also check the Perl OOP tutorial.
I would like to use the HTML::Template module. However, it is not installed on the server I'm using to develop CGI scripts.
Is it possible to load a module at runtime: I found the Template.pm file on my local Perl installation and uploaded the file to the server I'm using.
#!/usr/bin/perl -w
use CGI qw(:standard :html4);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
# use HTML::Template;
use Template;
# my $package = "HTML::Template";
# eval {
# (my $pkg = $package) =~ s|::|/|g; # require need a path
# require "$pkg.pm";
# import $package;
# };
# die $# if( $# );
# open the HTML template
my $template = HTML::Template->new(filename => 'test.tmpl');
# fill in some parameters in the template
$template->param(home => $ENV{HOME});
$template->param(path => $ENV{PATH});
# send the obligatory Content-Type
print "Content-Type: text/html\n\n";
# print the template
print $template->output;
Here is what I do:
cgi-bin/script.pl
cgi-bin/lib/HTML/Template.pm
In script.pl (unless you are running under mod_perl):
use FindBin qw( $Bin );
use File::Spec::Functions qw( catfile );
use lib catfile $Bin, 'lib';
use HTML::Template;
# The rest of your script
If HTML::Template is truly optional, read perldoc -f require.
See also How do I keep my own module/library directory? and What's the difference between require and use? in perlfaq8.
This is similar to Sinan's answer, but uses local::lib:
Set up your files as:
cgi-bin/script.pl
cgi-bin/lib/HTML/Template.pm
And in your script:
use strict;
use warnings;
use local::lib 'lib';
use HTML::Parser;
The advantage of local::lib is you can install modules from CPAN directly into a directory of your choosing:
perl -MCPAN -Mlocal::lib=lib -e 'CPAN::install("HTML::Parser")'
HTML::Template and Template are different Perl modules. If you want to use HTML::Template, you will need to use HTML::Template; at the top of the script to import that package.
Ensure that you copied the HTML/Template.pm file from your local machine to the server, rather than Template.pm.
I should have added this as an option, since I'm one of the maintainers of this module: App::FatPacker can be used to include a third-party module with your application when it ships, so it does not need to be installed separately in the deployment environment.
Yes it is. Look at Module::Runtime. I would install your HTML module though, even in a local install directory. It's probably less hassle.