2010-10-13 14 views
5

Próbowałem używać system() z fork(), próbowałem exec(), i nadal nie dostałem tego, czego potrzebuję.Jak mogę wykonać zewnętrzną komendę Windows i od razu zwrócić w Perlu?

Chcę napisać skrypt Perla, który uruchamia, powiedzmy, inny skrypt Perla 5 razy z rzędu (wysyłając różne wartości parametrów), ale powinien być uruchamiany jednocześnie. Zdaję sobie sprawę, mogę włączyć mój skrypt do pliku .pm i odwoływać się do niej, ale wolałbym, aby utrzymać niezależny skryptu dziecko rodzica ... systemu

  • () działa, ale wykonuje polecenia kolejno (sens za doc)
  • exec() nie robi praca - tylko ona wykonuje pierwsza metoda (sens za doc)
  • dodałem widelca(), aby perl dziecko skryptu, a następnie próbował za pomocą systemu ()
  • to też nie działa.
  • lewy apostrof 'Dokumenty dowodzenia mówi działa tak samo jak system() ...

nie Czy istnieje prosty sposób w Perl (im przy WindowsXP), aby wykonać proces, a nie dbać o Zwróć wartości lub zabierz i po prostu przejdź do następnego wiersza skryptu rodzica?

+1

post jakiś kod, dzięki czemu możemy zobaczyć, co nie działa. – Ether

Odpowiedz

8

W systemie Windows możesz nadać systemowi super-tajną flagę, IIRC.

system 1, @cmd; 

Szybkie wyszukiwanie google na to pytanie na perlmonks daje: http://www.perlmonks.org/?node_id=639814

nadzieję, że pomoże.

+0

to działało niesamowicie. Dzięki. Używanie perla po raz pierwszy działa dobrze. dziękuję wszystkim, którzy odpowiedzieli po moim komentarzu – dferraro

+0

@dferraro => witamy w magicznej krainie Perla, mam nadzieję, że spodoba ci się twój pobyt. Ogólnie zalecam, aby trzymać się z dala od rozwiązań specyficznych dla systemu operacyjnego, jeśli istnieje bardziej ogólne rozwiązanie. Nigdy nie wiadomo, kiedy skrypt będzie potrzebny do pracy na nieprzewidzianej platformie. –

+0

dzięki za powitanie ... Chciałbym teraz uciec jak diabli. Wciąż nie widziałem ani jednej linii perla, która nie zajęłaby mi 5 minut, by się przed nią obronić;) – dferraro

2

Musisz rozwidlić rodzica, a następnie wykonać polecenie w nowym procesie. To idzie tak, zakładając, że jest oryginalny scenariusz, a B jest jeden chcesz zrobić 5 razy:

   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 

itp

+0

Jak mogę rozwidlić rodzic? fork nie bierze params, więc jak mam powiedzieć, które polecenie wykonać ... – dferraro

+0

Najpierw wywołujesz ['fork'] (http://perldoc.perl.org/functions/fork.html). To powiela proces, jak pokazano, następnie 'fork' zwraca dwa razy. Następnie należy użyć wartości zwracanej, aby określić, w którym procesie się znajdujesz. Jeśli jest niezerowa, jest to rodzic; jeśli 0, to dziecko. Następnie, w dziecku, wywołujesz ['exec'] (http://perldoc.perl.org/functions/exec.html). Eric podał zwięzły przykład. –

12

można to zrobić tak (rozwidleniu rodzica, exec u dziecka):

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

sposób, który exec $cmd unless fork prac jest to, że fork zwróci wartość true w dominującej (identyfikator procesu) i zwróci wartość false w dziecku, co exec $cmd tylko zostanie uruchomione, jeżeli fork zwraca wartość false (a ka, u dziecka).

lub jeśli chcesz zachować zakładki na procesie, gdyż biegnie równolegle:

my @procs; 

for my $cmd qw(cmd1 cmd2 cmd3) { 

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

    push @procs, $handle; 
} 

następnie można odczytać z elementu @procs jeśli trzeba.

Można również rzucić okiem na jeden z wielu modułów cpan, takich jak Forks::Super, które obsługują szczegóły zarządzania widelcami.

+0

Pamiętaj, że fork() w systemie Windows ma pewne komplikacje, a ponieważ otwarty jest po prostu widelcem pod kołdrą, zobaczysz je również. – Tanktalus

2

Moduł jest przesadny dla tego zadania. Chcesz fork, aby utworzyć nowy proces, a następnie exec, aby uruchomić polecenie w nowym procesie.Aby uruchomić pięć komend, potrzebujesz czegoś takiego:

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

Moduł nie jest przesadą, jeśli chcesz, aby zachowanie na wielu platformach ukrywało wszystkie specyficzne dla platformy zachowanie, które powoduje emulację widelca w systemie Windows. . Ukrywanie złożoności za (miejmy nadzieję) prostym interfejsem jest jednym z celów modułów. – Tanktalus

+1

Jeśli masz wersję 5.8 lub nowszą, nie ma nic złego w fork i exec w systemie Windows. –

3

Bardzo lekkie podejście.

Windows:

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

UNIX:

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

Próbowałem tego, ponieważ wyglądało to na proste, ale nie otwierało żadnych okien konsoli, a potem wisiało na ostatnim wykonaniu ...? – dferraro

+0

Ogólnie rzecz biorąc, lubię unikać blokad, aby uniknąć powłoki. Szczególnie w systemie Windows, w którym $ cmd może zawierać spacje. – Tanktalus

Powiązane problemy