in reply to Question: Best practices for packaging scripts
I would try to isolate your application as much as possible from the system it is being installed in. I view applications as guests on a machine - they should leave everything the way they found it.
This is clearly easier to do if everything used by your application is self-contained. When items are shared, uninstalling an application can be really difficult. Unless your application is being installed by a package manager that keeps track of how many applications are using module X (e.g. you wrapped your CPAN modules in a .deb or .rpm), you won't be able to tell if a shared module X might be in use by some other application.
Keeping every thing separate also saves you from a nightmare of version compatibility issues. You don't have to worry about your application breaking if other applications need older or newer versions of a module.
Yes, this means you might have more than one copy of module X, but at least you won't be in Perl's version of DDL/JAR hell. A common store of non-core modules for all applications is generally only a good idea if you are running a server box or test machine dedicated to a set of applications or administration scripts where you have full control over what versions will need.
Manually setting up PERL5LIB is a pain. When I produce self-contained applications, I generally put the modules in a sub-directory. I always know its location relative to the script and hard code that relative path. When the script starts up, I get the location of the script using some script magic (see below), and then convert the hard coded relative path into a real path and add the real path to @INC
Getting the actual location of the script is a bit tricky. Two things can get in the way: symbolic links and mod_perl. In *nix systems there is a long standing practice of placing a symbolic link to scripts in either /usr/bin or /usr/local/bin. Thus __FILE__ contains a symbolic link rather than the actual location of the file. To get the scripts actual location from the script alone, one has to get to the real file behind the symbolic link. To simplify the process of finding the real script, you can use the module Find::Bin
I haven't done much work with mod_perl (we use FastCGI), but as I understand it mod_perl presents another problem: scripts are loaded as modules. This means that __FILE__ is often only a partial path. To find the module's actual location, one needs to look up the module in %INC.
The script below illustrates a way to find the location of your module directory (e.g. myapp/lib) from your script file's location:
# placed in a begin block so it gets executed before we # try to load any modules. use XXX statements for non-core # modules should be placed after this begin block BEGIN { # Taint mode will complain unless you set these paths. $ENV{PATH} = ""; $ENV{CDPATH} = ""; sub calcLib { if (caller(3)) { #this is loaded as module: caller(3) returns the files caller #can't use __FILE__ between {} my $sModuleFile = __FILE__; $sModuleFile = $INC{ $sModuleFile }; return $sModuleFile =~ /bin\/[^\/]+$/ ? "$sModuleFile/../../lib" : "$sModuleFile/.."; } else { #this is the main entry point: caller(3) returns no caller #use FindBin to get the full file path of this directory #untaint FindBin::Bin my $sModuleDir = $1 if ($FindBin::Bin =~ m/^(.*)$/); return $sModuleDir =~ m/\/bin$/ ? $sModuleDir . "/../lib" : $sModuleDir; } } use lib (calcLib); }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Question: Best practices for packaging scripts
by jujiro_eb (Sexton) on Mar 27, 2009 at 14:24 UTC | |
by ELISHEVA (Prior) on Mar 27, 2009 at 15:02 UTC |