这是我尝试解决引发的无关问题"Why don’t my system calls work in the Perl program I wrap with pp?"我在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 # unzip -l ls_test Archive: ls_test Length Date Time Name -------- ---- ---- ---- 0 07-13-09 16:41 script/ 436 07-13-09 16:41 MANIFEST 214 07-13-09 16:41 META.yml 93 07-13-09 16:41 script/ls_test.pl 538 07-13-09 16:41 script/main.pl 16 07-13-09 16:20 out_test.sh -------- ------- 1297 6 files
如果我在其他空目录中运行压缩文件,则找不到shell脚本:
new-net:~/test # ./ls_test total 3391 -rwxr-xr-x 1 root root 3466177 Jul 13 16:41 ls_test sh: out_test.sh: No such file or directory
如果我将shell脚本复制到目录中,则打包脚本将按预期运行:
new-net:~/test # ./ls_test
total 3395 -rwxr-xr-x 1 root root 3466177 Jul 13 16:41 ls_test -rw-r--r-- 1 root root 16 Jul 13 16:20 out_test.sh I'm here
那么,pp
打包脚本在哪里可以找到包含的文件?如何在原始Perl脚本中配置对该包含文件的调用?
答案 0 :(得分: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' } );
您还可以创建与您要运行的脚本同名的可执行文件的symolic链接,然后运行它们。
实际上,重新阅读您的问题,只需访问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;
答案 1 :(得分:4)
感谢大家为这个答案做出贡献。我正在添加这个答案,以提炼出每个人的宝贵意见,我过去常常提出在我的特定应用程序中为我工作的解决方案。
应用程序使用POE和Tk在ActiveState Perl中编写,并打包使用pp进行分发。它使用了几个外部文件;一些用于输入程序(来自DNS的数据),一些用于用户采取的操作(创建和删除DNS别名记录)。
PAR packer(pp)包含使用-a参数的外部文件。这些文件将解压缩到包中创建的“临时”路径下的\ 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提供这个优秀的环境。
答案 2 :(得分:3)
这是我的系统有用的东西:
C:\tmp> cat build.bat @echo off mkdir output call pp -o runner.exe runner.pl -a sayhello.bat move runner.exe output\runner.exe
C:\tmp> cat sayhello.bat @echo I am saying hello ...
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 ...
<<<
但感觉有点脏。