6

这是我试图解决提出的无关问题“为什么我的系统调用不能在我用 pp 包装的 Perl 程序中工作?” 我在 linux 系统上创建了一个简单的 Perl 脚本:

new-net:~/scripts # cat ls_test.pl
@ls_out = `ls -l`;

map { print "$_\n" } @ls_out;

$out = `sh out_test.sh`;

print "$out\n";

该脚本调用一个简单的 shell 文件:

new-net:~/scripts # cat out_test.sh
echo "I'm here"

我使用 pp 将 Perl 脚本与 shell 脚本一起打包到 ls_test 中:

new-net:~/test # 解压 -l ls_test
存档:ls_test
  长度 日期 时间 名称
 -------- ---- ---- ----
        0 07-13-09 16:41 脚本/
      436 07-13-09 16:41 清单
      214 07-13-09 16:41 META.yml
       93 07-13-09 16:41 脚本/ls_test.pl
      538 07-13-09 16:41 脚本/main.pl
       16 07-13-09 16:20 out_test.sh
 -------- --------
     1297 6 档

如果我在一个空目录中运行打包文件,则找不到 shell 脚本:

新网:~/test # ./ls_test
总计 3391

-rwxr-xr-x 1 root root 3466177 Jul 13 16:41 ls_test

sh: out_test.sh: 没有这样的文件或目录

如果我将 shell 脚本复制到目录中,打包的脚本会按预期运行:

新网:~/test # ./ls_test
总计 3395 -rwxr-xr-x 1 root root 3466177 Jul 13 16:41 ls_test -rw-r--r-- 1 根 16 Jul 13 16:20 out_test.sh 我在这

那么,pp打包的脚本希望在哪里找到包含的文件?以及如何在原始 Perl 脚本中配置对该包含文件的调用?

4

3 回答 3

6

打包的可执行文件中的文件被提取到一个临时目录(通常是 /tmp/par-USERNAME/cache-XXXXXXX)。要访问这些文件,请执行以下操作:

#!/usr/bin/perl

# Reads a data file from the archive (added with -a)
print PAR::read_file("data");

# Will execute "script2" in the archive and exit. Will not return to this script.
require PAR;
PAR->import( { file => $0, run => 'script2' } );

您还可以创建与要运行的脚本同名的可执行文件的符号链接,然后运行它们。

实际上,重新阅读您的问题,简单地访问 PAR_TEMP 环境变量可能更有用:

#!/usr/bin/perl
use File::Slurp qw(slurp);

$data_dir = "$ENV{PAR_TEMP}/inc";
$script_dir = "$data_dir/script";

print slurp("$data_dir/datafile");

# file access permissions are not preserved as far as I can tell,
# so you'll have to invoke the interpreter explicitly.
system 'perl', "$script_dir/script2", @args;
于 2009-07-14T15:44:07.740 回答
4

感谢大家为这个答案做出贡献。我添加这个答案是为了提炼出每个人的宝贵意见,我曾经提出在我的特定应用程序中对我有用的解决方案。

该应用程序使用 POE 和 Tk 用 ActiveState Perl 编写,并使用 pp 打包分发。它使用了几个外部文件;一些用于输入程序(来自 DNS 的数据),一些用于用户采取的操作(创建和删除 DNS 别名记录)。

PAR 打包程序 (pp) 使用 -a 参数包含外部文件。这些文件被解压到包创建的“temp”路径下的 \inc 目录中,并可通过

$ENV{PAR_TEMP}

解决方案的第一步是将此信息添加到 POE“$heap”。下面的行处于在线状态“_start”;

$heap->{t_path} = "$ENV{PAR_TEMP}\\inc\\";

当我在 Win32 环境中工作时,我使用转义的反斜杠将 \inc 目录附加到临时路径中。

当调用外部文件输入应用程序时,我使用了一个变量(@zone)来返回数据;

@zone = `$heap->{t_path}dnscmd aus-dc1 /enumrecords company.pvt @`;

对于完成外部操作的调用,调用文件而不保存输出;

`$heap->{t_path}cpau -dec -file $heap->{t_path}del_event.job -nowarn -wait`;

再次感谢大家的贡献,感谢 stackoverflow 提供了这个很棒的环境。

于 2009-07-15T16:14:12.347 回答
3

这是在我的系统上工作的东西:

C:\tmp> cat build.bat
@echo 关闭
mkdir 输出
调用 pp -o runner.exe runner.pl -a sayhello.bat
移动 runner.exe 输出\runner.exe
C:\tmp> cat sayhello.bat
@echo 我在打招呼...

C:\tmp> cat runner.pl
#!/usr/bin/perl

use strict;
use warnings;

use File::Spec::Functions qw( catfile );

my $prog_path = catfile $ENV{PAR_TEMP}, inc => 'sayhello.bat';

my $output = `$prog_path`;

print "The output was: >>> $output <<< ";

__END__

输出:

C:\tmp\output> runner.exe
The output was: >>> I am saying hello ...
<<<

不过,这感觉有点脏。

于 2009-07-14T18:08:31.553 回答