2009-07-14 12 views
6

Questo è il mio tentativo di tagliare le questioni estranee sollevate "Why don’t my system calls work in the Perl program I wrap with pp?" Ho creato un semplice script Perl su un sistema Linux:Dove apre pp (PAR) i file add (-a)?

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

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

$out = `sh out_test.sh`; 

print "$out\n"; 

Questo script richiama un semplice file di shell:

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

ho usato pp per confezionare lo script Perl con lo script di shell in 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 

Se eseguo il file compresso in un altro modo e directory mpty, lo script di shell non è stato trovato:

 
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 

Se copio lo script di shell nella directory, lo script imballato viene eseguito come previsto:

 
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

Allora, da dove viene uno script ricco pp aspettano trovare un file incluso? E come deve essere configurata una chiamata al file incluso nello script Perl originale?

risposta

6

I file in un pacchetto eseguibile vengono estratti in una directory temporanea (in genere/tmp/par-USERNAME/cache-XXXXXXX). Per accedere a questi file fare qualcosa di simile al seguente:

#!/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' }); 

È inoltre possibile creare collegamenti symolic per l'eseguibile che hanno lo stesso nome dello script che si desidera eseguire, e farli funzionare.

In realtà, rileggendo la tua domanda, è sufficiente accedere alla variabile d'ambiente PAR_TEMP è probabilmente più utile:

#!/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

da PAR perldoc; run Il nome di uno script da eseguire nel par. Esce quando finito. Significa che qualsiasi chiamata a un file aggiunto esce dallo script impacchettato? Il problema che stavo originariamente cercando di risolvere è uno script POE/TK che richiama vari file esterni dai comandi del widget. – jpolache

3

Qui è qualcosa che ha lavorato sul mio sistema:

 
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__ 

Uscita:

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

Questo si sente un po 'sporco, però.

+0

Sembra su MSWindows la directory cache/temp predefinita per PAR è la directory corrente. – Inshallah

+2

No, C: \ DOCUME ~ 1 \ nomeutente \ LOCALS ~ 1 \ Temp \ par-username \ cache-07b6bc6c42c824d8fdd5abd08eb8b67b2bf7ecab ... Tuttavia, il tuo commento mi ha fatto capire che avevo dimenticato di sistemare 'build.bat' nel post . –

+1

L'utilizzo di PAR_TEMP è sporco? Non ho trovato altri mezzi per fare riferimento alla directory di estrazione. Puoi ovviamente estrarre l'archivio da solo, quindi sai dove si trova. – Inshallah

4

Grazie a tutti per aver contribuito a questa risposta. Sto aggiungendo questa risposta per distillare le parti dell'input inestimabile di tutti che ho usato per trovare la soluzione che ha funzionato per me nella mia particolare applicazione.

L'app è scritta in ActiveState Perl utilizzando POE e Tk e confezionata per la distribuzione in pp. Fa uso di diversi file esterni; alcuni per l'inserimento nel programma (dati munged dal DNS) e alcuni per le azioni intraprese dall'utente (creazione e cancellazione di record alias DNS).

Il packer PAR (pp) include file esterni che utilizzano l'argomento -a.Questi file vengono spacchettati nella directory \ inc sotto un percorso "temp" creato dal pacchetto e disponibile per lo script tramite

$ENV{PAR_TEMP}

Il primo passo per la soluzione era quella di aggiungere queste informazioni al POE "$ mucchio" . La riga sottostante è nello stato "_start" in linea;

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

Come sto lavorando in ambiente Win32, ho usato il backslash escape per aggiungere la directory \ inc nel percorso temporaneo.

Quando si chiama un file esterno per l'input nell'applicazione, ho utilizzato una variabile (@zone) per restituire i dati;

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

Per le chiamate per completare le azioni esterne, i file vengono richiamati senza salvare l'output;

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

Grazie ancora a tutti per aver contribuito e grazie a StackOverflow per la fornitura di questo grande ambiente.

+3

usa 'File :: Spec-> catfile ($ ENV {PAR_TEMP}, 'inc')' piuttosto che scherzare con doppi backslash. A proposito, sono un po 'sorpreso che io sia l'unico che ha messo in svantaggio qualsiasi risposta in questo thread: il modo in cui mostri apprezzamento in SO è quello di aumentare le risposte. –