J'ai récemment écrit un nouveau script Perl pour tuer les processus basés sur le nom du processus/nom d'utilisateur et je l'ai étendu à l'aide de classes afin de pouvoir réutiliser le code de processus dans d'autres programmes. Ma disposition actuelle est -
/home/mutew/src/prod/pskill <-- Perl script
/home/mutew/src/prod/Process.pm <-- Package to handle process descriptions
J'ai ajouté ~/src/prod dans ma variable $ PATH pour accéder au script de n'importe où. L'exécution du script à partir de tout répertoire autre que son répertoire résident entraîne un "Impossible de localiser Process.pm dans @INC" (ce qui est compréhensible étant donné que, à part les répertoires partagés dans/usr, @INC inclut uniquement le répertoire actuel - '.'). Une solution de contournement que j'utilise est la directive use lib comme telle -
use lib '/home/mutew/src/prod';
mais c'est un problème majeur de portabilité. Des solutions qui me permettront également d'exporter le script vers d'autres systèmes sans et changements?
MODIFIER
L'approche la plus simple que j'ai trouvée consiste à utiliser le module FindBin. Comme ça:
use FindBin;
use lib $FindBin::Bin;
En général, je préfère que mes scripts soient fournis de manière à ce que les programmes se trouvent dans le répertoire/bin et les bibliothèques dans le répertoire/lib
Dans ces situations, j'utilise une approche légèrement plus compliquée:
use Cwd qw(abs_path);
use FindBin;
use lib abs_path("$FindBin::Bin/../lib");
L'appel abs_path consiste à faire en sorte que @INC contienne tout/lib, et non pas/bin /../ lib - c'est juste un léger changement, mais cela facilite la lecture des messages d'erreur.
Je suis curieux de savoir pourquoi la solution simpliste
use File::Basename;
use lib dirname (__FILE__);
use SomeModuleLocatedInTheSameDirectoryAsThisPerlScriptOrModule;
n'est pas venu. Le module FindBin semble avoir quelques problèmes si le fichier n'est pas le script Perl exécutable principal, mais simplement un module Perl non exécutable. C'est du moins ainsi que j'interprète le commentaire dans la documentation . Je ne l'ai pas vraiment testé.
Pour avoir un autre chemin d'accès par rapport à l'emplacement de ce fichier Perl, faites quelque chose comme
use File::Basename;
use lib dirname (__FILE__) . "/MyModules";
De perlfaq8 , qui répond "Comment ajouter un répertoire à mon chemin d'inclusion (@INC) lors de l'exécution?" . Il existe également plusieurs autres réponses aux questions concernant ce problème.
Comment ajouter un répertoire à mon chemin d'inclusion (@INC) lors de l'exécution?
Voici les façons suggérées de modifier votre chemin d'inclusion, y compris les variables d'environnement, les commutateurs d'exécution et les instructions dans le code:
la variable d'environnement PERLLIB
$ export PERLLIB=/path/to/my/dir
$ Perl program.pl
la variable d'environnement Perl5LIB
$ export Perl5LIB=/path/to/my/dir
$ Perl program.pl
l'indicateur de ligne de commande Perl -Idir
$ Perl -I/path/to/my/dir program.pl
l'utilisation lib pragma:
use lib "$ENV{HOME}/myown_perllib";
Ce dernier est particulièrement utile car il connaît les architectures dépendantes de la machine. Le module pragmatique lib.pm a été inclus pour la première fois avec la version 5.002 de Perl.
Jetez un oeil à Par :: Packer . Il crée un exécutable avec toutes les dépendances du script incluses. Cela facilite la distribution. Vous pouvez également fournir à vos utilisateurs une version de votre module qui peut être installée sur leurs systèmes. Voir Module :: Starter pour un moyen facile de construire tous les fichiers requis pour faire une distribution standard de style CPAN.
Vous pouvez faire apparaître Perl dans n'importe quel répertoire en utilisant le -I
drapeau. Ici, -I
signifie @INC
qui est le tableau des chemins dans lesquels Perl recherche les modules. En utilisant -I
ajoute le chemin donné au @INC
tableau pour cette exécution.
par exemple:
Perl -I lib bin/script.pl
où lib contient les modules que je veux utiliser.
Je sais que cela fonctionne pour Perl 5. Je ne suis pas sûr des autres versions.
Outre les solutions déjà énoncées:
"L'approche la plus simple" (™) que j'utilise lors du développement/test d'un module avant de le déployer (dans/usr/local/lib/site_Perl/ou ailleurs dans @INC) consiste à modifier @INC avant de charger le module comme suit:
#!/usr/bin/Perl
use strict;
use warnings;
# Modify @INC prior to module loading.
BEGIN { unshift @INC, '.'; }
use YourModuleInCWD;
( Ajouter le répertoire de travail actuel à @INC? - PerlMonks )
Pour convertir des liens relatifs en absolus et les ajouter à @INC, j'utilise normalement ex :: lib. Bien sûr, cela n'est utile que si vous prévoyez de conserver les emplacements relatifs du script et du module identiques sur toutes les machines sur lesquelles vous prévoyez d'exécuter votre script.