2010-10-13 10 views
5

Ho provato a usare system() con fork(), provato exec(), e ancora non ho ottenuto ciò di cui ho bisogno.Come posso eseguire un comando Windows esterno e ritornare immediatamente in Perl?

Voglio scrivere uno script Perl che esegue, diciamo, un diverso script Perl 5 volte di seguito (inviando valori di parametri diversi), ma farlo funzionare contemporaneamente. Mi rendo conto che avrei potuto girare il mio script in un file .pm e fare riferimento a esso, ma preferirei mantenere indipendente sceneggiatura figlio del genitore ...

  • sistema() funziona, ma esegue i comandi consecutivamente (senso per doc)
  • exec() non funziona - venga eseguita solo il primo metodo (senso per doc)
  • ho aggiunto una forcella() alla scritto bambino perl e poi provato utilizzando il sistema (
  • anche questo non ha funzionato.
  • apice inverso documenti comando 'dice che funziona allo stesso modo del sistema() ...

non c'è un modo semplice in Perl (im utilizzando Windows XP) per eseguire un processo, e non si preoccupano del restituisce valori o qualcosa e continua semplicemente nella riga successiva dello script genitore?

+1

postale po 'di codice, in modo che possiamo vedere ciò che non ha funzionato. – Ether

risposta

8

Su Windows, è possibile assegnare il flag super-secret 1 al sistema, IIRC.

system 1, @cmd; 

Una rapida ricerca su Google per questa domanda PerlMonks dà: http://www.perlmonks.org/?node_id=639814

Speranza che aiuta.

+0

ha funzionato alla grande. Grazie. La prima volta che uso perl, funziona alla grande. grazie a tutti gli altri che hanno risposto dopo il mio commento – dferraro

+0

@dferraro => benvenuto nella magica terra di Perl, spero che il tuo soggiorno sia piacevole. In generale, ti consiglio di stare lontano dalle soluzioni specifiche del sistema operativo se esiste una soluzione più generale. Non sai mai quando avrai bisogno che la sceneggiatura funzioni su una piattaforma imprevista. –

+0

grazie per il benvenuto ... mi piacerebbe scappare via all'inferno ora. Non ho ancora visto una sola riga di perl che non mi ha portato 5 minuti a sovrastimarlo;) – dferraro

2

È necessario inserire il parent e quindi eseguire il nuovo processo. Si va come questo, supponendo che A è la sceneggiatura originale, e B è quello che si desidera fare 5 volte:

   A1 
fork in A1 -> A1 A2 
exec B in A2 -> A1 B2 
fork in A1 -> A1 A3 B2 
exec B in A3 -> A1 B3 B2 

ecc

+0

Come posso sborsare il genitore? fork non accetta parametri, quindi come faccio a sapere quale comando eseguire ... – dferraro

+0

Prima chiamate ['fork'] (http://perldoc.perl.org/functions/fork.html). Questo duplica il processo come mostrato, quindi 'fork' restituisce due volte. Quindi si utilizza il valore di ritorno per determinare in quale processo ci si trova. Se è diverso da zero, è il genitore; se 0, quindi il bambino. Quindi, nel bambino, si chiama ['exec'] (http://perldoc.perl.org/functions/exec.html). Eric ha fornito un esempio conciso. –

12

si può fare in questo modo (forchetta nel genitore, exec nel bambino):

for my $cmd qw(command1 command2 command3) { 
     exec $cmd unless fork 
} 

il modo in cui i exec $cmd unless fork funziona è che fork restituirà un vero valore nel genitore (il processo id) e restituirà un valore falso nel bambino, in tal modo exec $cmd solo viene investito se fork restituisce falso (a Ka, nel bambino).

o se si vuole tenere sotto controllo il processo come corre in concomitanza:

my @procs; 

for my $cmd qw(cmd1 cmd2 cmd3) { 

    open my $handle, '-|', $cmd or die $!; 

    push @procs, $handle; 
} 

allora si può leggere da un elemento di @procs se è necessario.

Oppure dare uno sguardo a uno dei numerosi moduli cpan come Forks::Super che gestiscono i dettagli della gestione delle forcelle.

+0

Ricorda che fork() su Windows ha alcune complicazioni e dal momento che l'apertura è semplicemente una forchetta sotto le coperte, le vedrai anche lì. – Tanktalus

2

Un modulo è eccessivo per questo lavoro. Si desidera fork per creare un nuovo processo e quindi exec per eseguire un comando nel nuovo processo.Per eseguire cinque comandi, è necessario qualcosa del tipo:

for (my $i=0; $i<5; $i++) { 
    if (fork() == 0) { 
     exec($command[$i]); # runs command, doesn't return 
    } 
} 
+0

Un modulo non è eccessivo se si desidera un comportamento multipiattaforma che nasconda tutto il comportamento specifico della piattaforma che l'emulazione di fork su Windows apporta . Nascondere la complessità dietro un'interfaccia semplice (si spera) è uno degli scopi dei moduli. – Tanktalus

+1

Se hai la versione 5.8 o successiva, non c'è niente di sbagliato in fork ed exec su Windows. –

3

Un approccio molto leggero.

di Windows:

foreach my $cmd (@cmds) 
{ 
    `start $cmd`; 
} 

Unix:

foreach my $cmd (@cmds) 
{ 
    `$cmd &`; 
} 
+0

Ho provato questo perché sembrava semplice, ma non ha aperto nessuna finestra della console e poi è apparsa sull'ultima esecuzione ...? – dferraro

+0

Generalmente, mi piace evitare i backtick solo per evitare la shell. Soprattutto su Windows dove $ cmd potrebbe contenere degli spazi. – Tanktalus

Problemi correlati