Internal server error when modperl use module - perl

I try write an perl_mod script, but it say: "Internal Server Error".
this is module file: (mm1.pm)
package mm1;
use strict;
use XML::Simple;
use DBI;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT_OK = qw(asd);
our #EXPORT = qw(asd);
sub asd(){
print "2222";
}
this is main file: (main.perl)
#!/usr/bin/perl -w
use strict;
use CGI qw/:standard/;
use CGI::Carp qw/fatalsToBrowser warningsToBrowser/;
use mm1;
print header(-type => 'text/html', -charset=>'utf-8');
print "asdasd";
If i try run without "use mm1;" this main.perl then succeed.
What is the problem?
Thanks!

That's not a mod_perl module, it's a CGI program.
The (first) problem is almost certainly the fact that you've omitted the 1; from the end of your module file. But looking in the web server error log will confirm that.

Related

Perl namespace problem: using exported functions in modules not working

I'm packaging some common functions in a small Perl module, that I load in the script using
use lib path/to/lib
In the module file I imported some other system installed modules (e.g. Carp qw(confess), but I cannot invoke confess directly, but rather Carp::confess, which is unusual to me.
This is my (non)-working example:
https://github.com/telatin/bioinfo/blob/master/mini/script.pl
use 5.012;
use FindBin qw($Bin);
use lib "$Bin/Demo/lib";
use Local::Module;
say "Version: ", $Local::Module::VERSION;
Local::Module->new();
The module: https://github.com/telatin/bioinfo/blob/master/mini/Demo/lib/Local/Module.pm
use 5.012;
use warnings;
use Carp qw(confess);
package Local::Module;
$Local::Module::VERSION = 2;
sub new {
my ($class, $args) = #_;
my $self = {
debug => $args->{debug},
};
my $object = bless $self, $class;
confess "Unable to create fake object";
return $object;
}
1;
What should I do in the .pm file to avoid this problem?
The problem is here:
use 5.012;
use warnings;
use Carp qw(confess);
package Local::Module;
First you load Carp and import confess, but at that point you're still in package main, so confess is imported into main.
Then you switch packages with package Local::Module, but there is no confess function defined here.
You need to switch packages first:
package Local::Module;
use 5.012;
use warnings;
use Carp qw(confess);
Now all imports and all the following code are in the same package.

Undefined subroutine &main::key_enc

I have a Perl module named McuEnc.pm which is located at /home/eric/temp directory:
package McuEnc;
use 5.010;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK = qw(key_enc data_enc data_dec);
sub key_enc { some code }
sub data_enc { some code }
sub data_dec { some code }
1;
I have a Perl script named test.pl which is also located at /home/eric/temp directory:
use 5.010;
use strict;
use warnings;
use McuEnc qw(key_enc data_enc data_dec);
key_enc("1111");
...
I have changed working directory to /home/eric/temp. Now if I run test.pl script, it runs correctly. But if I create a new directory /home/eric/temp/My and move the McuEnc.pm file into it and then modify the test.pl script as follwoing:
use 5.010;
use strict;
use warnings;
use My::McuEnc qw(key_enc data_enc data_dec);
key_enc("1111");
...
then I'm getting the following error when I run test.pl again:
Undefined subroutine &main::key_enc called at ./test line 6.
However, I can still call the subroutine correctly with:
McuEnc::key_enc("1111");
So why I'm getting the error message? what is wrong?
This was answered by Sobrique in the comments, but it was never posted as an official answer:
"The use statement doesn't match the package statement. Try package My::McuEnc instead"

Perl Module::Load fails

I tried to using Module::Load to dynamically load plugin from directory, but it doesn't work, even after maximal simplifing the code.
Main file:
#!/usr/bin/perl
use strict;
use warnings;
use Module::Load;
Module::Load::load_remote('Package', 'plugins/Blank.pm') or die;
plugins/Blank.pm:
#!/usr/bin/perl
package plugins::Blank;
use strict;
use warnings;
1;
But it still die. When i remove '...or die' part, it no dies, but Package still not loaded.
Module::Load::load_remote dies when failing, but does not return anything. Your example works fine for me, and the package is loaded. If it doesn't load the package it should die inside load_remote. load_remote only loads the functions that are exported into the other namespace. It also only seem to work if the other module is loaded as a module name, instead of a filename:
load.pl:
#!/usr/bin/perl
use strict;
use warnings;
use Module::Load;
Module::Load::load_remote("Package","plugins::Blank","hw");
Package::hw();
plugins/Blank.pm:
package plugins::Blank;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK = qw(hw);
sub hw {
print "Hello World\n";
}
1;
Outputs:
Hello World
But to achieve what you want you can probably use an approach like this:
#!/usr/bin/perl
use strict;
use warnings;
use Module::Load;
my $pkg = 'plugins::Blank';
Module::Load::load($pkg);
$pkg->hw();

Why doesn't my Perl script use my module?

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");

How can I load a Perl module at runtime?

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.