2009-11-10 48 views
7

如何在不强制用户知道脚本运行所需的自定义(非CPAN)模块的情况下,如何分发本机(非“编译/ perl2exe/...”)Perl脚本?如何在没有自定义模块开销的情况下分发本地perl脚本?

问题是,用户将不可避免地将脚本复制到系统的其他位置,并将脚本从本机环境中取出,然后再无法找到需要运行的模块。

我有时只是将模块复制到实际的脚本中解决,但我更喜欢更清洁的解决方案。

更新:我更好地澄清。我分发了一些恰好在后端使用类似模块的脚本。用户知道如何运行Perl脚本,而不是依靠告诉他们“不要移动脚本”,我宁愿让他们移动文件。阻力最小的路径。

+1

这些模块是否为特定脚本专用,还是由多个脚本共享?前一种情况通常通过将模块放置在* .pl文件旁边的lib文件夹中来实现。后者意味着将模块安装到站点/ lib或PERL5LIB中的其他位置。 – 2009-11-11 16:21:28

回答

4

如果您为客户端准备的脚本需要“自定义”模块,则只需打包模块,就好像您尝试将它们上载到cpan一样。然后将包提供给客户端,他可以使用cpan实用程序来安装脚本和模块。

+0

嗯......也许吧。我把这个问题看作是“最终用户在安装后移动* .pl”(可能假设它是自包含的),而不是如何安装。 – 2009-11-10 19:15:47

+4

我把它看作是“如何安装模块以及脚本?”。恕我直言,包本身也可以安装脚本这一事实只是一个额外的好处。 – innaM 2009-11-10 19:21:33

+4

我怀疑原始的“安装”包含“解压这个文件”,而用户没有意识到这些文件之间的依赖关系。如果安装涉及更多 - 比如通过调用cpan或运行安装脚本 - 那么简单移动.pl文件的诱惑将消失。它是否需要是非物质的;一个复杂安装的纯粹幻象*将足以保持文件的位置。 – 2009-11-10 21:23:15

6

正确的方法是告诉他们“不要那样做!”我希望他们不会期望移动一个exe文件并让程序继续工作。这也不例外。

也就是说,有两种选择。一种是用包装器(例如pl2bat)替换脚本,该包装器知道真实脚本的完整路径。另一种方法是使用PAR,但这需要安装PAR和/或parl(来自PAR :: Packer)。

+0

+1没有必要downvote这个。 OP的要求是矛盾的。 – 2009-11-10 19:21:20

+0

我只想欣赏关于*为什么有人认为它无益的评论。 – 2009-11-10 19:42:12

+0

我对你的答案的两个部分都有问题。从一般IT背景来看,我并不认为期望已知的用户行为改变以适应一个模糊的技术要求是不现实的。此外,我认为没有正式的安装程序的exe文件/应该/从系统的任何地方工作。如果程序具有外部依赖性,那么应该正确安装这些程序,以便文件系统中的位置无关紧要。 – 2009-11-10 19:57:57

2

与脚本一起分发安装程序。安装程序将需要以root权限运行,并将自定义模块放入标准系统位置(/ usr/local/lib/perl5/site_perl或其他)。

我还没试过这个,但Module::Install在这方面看起来很有帮助。它描述为:

独立的,可扩展的Perl模块安装

+0

将特定于应用程序的模块安装到系统范围的位置是处理文件/名称空间冲突风险的好方法。 – 2009-11-10 19:13:48

+2

我认为对所有的东西都有权衡,但是有一点深谋远虑可以将命名空间冲突的风险降低到Perl模块的几乎为零的风险。作者可以简单地创建一个基于他的名字或公司名称的顶级命名空间,并且极有可能是独一无二的。 – 2009-11-10 19:34:22

+0

Module :: Installer实际上并没有做任何你无法从Module :: Build或ExtUtils :: Makemaker中获得的东西。 – 2009-11-11 18:06:30

0

这将是非常好的,如果你可以只使用一个NeXTSTEP style application包。既然你可能没有开发一个使用bundle的平台,你必须要做。

将所有支持文件放入已知位置,并将可执行文件指向这些文件以访问设置和库。最简单的方法是使用简单的安装程序。

例如,一个名为foo一个应用程序,把所有必需的文件在/opt/xlyd_apps/foo,图书馆/opt/xlyd_apps/foo/lib,配置/opt/xlyd_apps/foo/etc,等等。将可执行文件放入/opt/xlyd_apps/foo/bin

重要的是要确保可执行文件知道在/opt/xlyd_apps/foo中查找它的所有好东西,因此如果客户/客户端将foo脚本移动到新位置,安装仍然有效。

因此,虽然您不能使整个事物自包含并可重定位,但您已使实际调用脚本可重定位。

+0

这只是硬编码应用程序中的库路径。这似乎不是一个很好的方法*除非*它是平台的一个功能。也许增加间接步骤会让事情变得更加安全。将您的自定义模块放入一些/ opt ...文件夹中,然后将一个超级简单的模块安装到知道定制模块路径的系统库中。这样,您不会在多个位置对路径进行硬编码。 – tsee 2009-11-11 09:07:50

2

由于“把你的模块都在一个地方,让你的应用程序意识到这一点”,将甚至可以跨多个计算机和网络的工作,也许你应该看看PAR::Repository分别PAR::Repository::Client的变体。您只需提供一个连接到存储库(通过文件系统或https)的单个二进制客户端可执行文件,并执行由用户请求的存储库提供的任意数量的程序(使用任意一组模块)。

如果用户很多,这对维护也有好处:只需更新存储库提供的软件,用户在下次启动程序时就会开始使用系统的更新代码。

+0

不是这样的需要他们有这些模块安装在他们的Perl安装?或者它是完全独立的东西? – dlamotte 2009-11-11 15:42:23

+0

PAR :: Packer产生完全独立的二进制可执行文件。但是,它会将所有依赖关系与应用程序打包在一起。因此,如果您希望在多个应用程序之间共享代码,则可能不太合适。 (PAR提供了多种方法来解决这个问题,但是我的注释长度已经用完了。)在存储库场景中,您只需发布一个loader.exe,可以根据需要从存储库中获取应用程序和依赖项。另请参阅:http://steffen-mueller.net/talks/appdeployment/ – tsee 2009-11-11 16:48:03

-3

我真的想出了我自己的解决方案,我很好奇它会有什么样的接待。

我写了一个脚本,它读取一个perl脚本并查找“use/require”语句。找到它们后,它会检查模块是否是标准库的一部分(查看/perl5/\d+.\d+[\d.]+/的模块路径),然后用两种不同的方式重写使用/需求行,具体取决于用法。

如果需要发现:

{ 
    ... inline the entire module here... 
} 

如果发现使用

BEGIN { import Module ...imports seen... } 

BEGIN { 
    ... inline the entire module here... 
} 

如果使用进口,立即按照上面

我明白这个不是使用XS模块,但我很好。大多数情况下,我只需要支持纯粹的perl模块。

+0

查看Module :: ScanDeps的依赖关系解析和Module :: CoreList来检查它是否带有默认库。 – tsee 2009-11-11 16:50:38

+0

除了它没有使用CPAN模块来做​​到这一点......这个过程为什么不好呢?答案的核心是你将模块文本嵌入到脚本中。你没有给出我为什么这么糟糕的原因。 – dlamotte 2009-11-11 19:00:57

+0

@xyld:如果它有效,那很好。但有很多情况下它不起作用(当然包括XS模块)。虽然我不记得当我沿着这条路线走下去的确切模块,但请相信我,这不是一个可靠的解决方案。那时候,我实际上写了一些中等复杂的代码来自动解决各种问题。从来没有完成它,并与我所知道的工作顺利。当我遇到我的企图时,我会通知你。 – tsee 2009-11-19 22:18:40

相关问题