2012-06-06 17 views
35

Chcę uruchomić kilka poleceń, z których każda nie kończy się, dopóki nie zostanie naciśnięty klawisz Ctrl-C. Czy jest coś, co mogę uruchomić, aby uruchomić je wszystkie naraz, a Ctrl-C opuści je wszystkie? Mogą udostępniać dane wyjściowe terminala.Uruchamiaj równolegle wiele poleceń jednocześnie na tym samym terminalu.

W szczególności mam kompas kompasu, kompilator coffeescript i niestandardowe polecenie, które obserwuje zmiany w plikach, wszystkie z uruchomionymi obserwacjami zmian plików. Nie chcę ładować terminala dla każdego polecenia.

Odpowiedz

73

Ten skrypt bash jest dla N wątków równoległych. Każdy argument jest poleceniem.

trap zabije wszystkie podprocesy po przechwyceniu SIGINT.
wait $PID_LIST oczekuje na zakończenie każdego procesu. Po zakończeniu wszystkich procesów program zostaje zamknięty.

#!/bin/bash 

for cmd in "[email protected]"; do { 
    echo "Process \"$cmd\" started"; 
    $cmd & pid=$! 
    PID_LIST+=" $pid"; 
} done 

trap "kill $PID_LIST" SIGINT 

echo "Parallel processes have started"; 

wait $PID_LIST 

echo 
echo "All processes have completed"; 

Zapisz ten skrypt jako parallel_commands i wykonaj go jako plik wykonywalny.
ten sposób korzystać z tego skryptu:

parallel_commands "cmd arg0 arg1 arg2" "other_cmd arg0 arg2 arg3" 

Przykład:

parallel_commands "sleep 1" "sleep 2" "sleep 3" "sleep 4" 

start 4 równoległe snu i czeka, aż "Sleep 4" wykończeń.

+1

Bardzo fajnie. Pułapka jest tym, czego szukałem. Zmienilem twoją odpowiedź na "wait", co tłumi niepotrzebne wiadomości "process x exited". –

+1

@MTsoul, 'wait' jest lepszy niż podczas pętli. Poprawiłem swój skrypt za pomocą Twojej sugestii. Działa teraz również dla N poleceń równoległych. –

+0

A co z uruchamianiem każdego cmd na jednym odrębnym rdzeniu? Powinienem uruchomić w następujący sposób: ./parallel_commands "taskset -c 0 cmd arg0 arg1 arg2" "taskset -c 1 inny_cmd arg0 arg2 arg3" lub taskset -c 2 ./parallel_commands "zestaw zadań -c 0 cmd arg0 arg1 arg2" "zestaw zadań -c 1 other_cmd arg0 arg2 arg3 " – user2517676

18

Wykorzystanie GNU równoległy:

(echo command1; echo command2) | parallel 
parallel ::: command1 command2 

Żeby zabić:

parallel ::: command1 command2 & 
PID=$! 
kill -TERM $PID 
kill -TERM $PID 
+1

To jest poprawna odpowiedź. https://www.gnu.org/software/parallel/ – 0atman

+1

@Oatman: Powinno być, ale GNU równoległe nie jest we wszystkich dystrybucjach. Na przykład RHEL 7 wydaje się nie mieć pakietu łatwo dostępnego. –

+0

Czy jest możliwe śledzenie PID procesu równoległego, który uruchamia wiele procesów i kończy je wszystkie przez zakończenie równoległego nadrzędnego? –

1

ja sugeruję znacznie prostsze narzędzie właśnie napisał. Obecnie nazywa się par, ale wkrótce zostanie zmieniona na parl lub pll, jeszcze nie zdecydowaliśmy.

https://github.com/k-bx/par

API jest tak proste, jak:

par "script1.sh" "script2.sh" "script3.sh" 

poprzedzenie polecenia mogą być wykonywane poprzez:

par "PARPREFIX=[script1] script1.sh" "script2.sh" "script3.sh" 
+1

Po próbie i niepowodzeniu tego, co opisałeś powyżej za pomocą gnu równoległego, udało mi się przy pierwszej próbie użycia twojego narzędzia. Dobra robota! – worldsayshi

+0

Pierwsza: 'parallel :::" script1.sh "" script2.sh "" script3.sh "' Druga normalnie użyłaby --tag: 'parallel --tag :::" script1.sh "" script2 .sh "" script3.sh "' –

25

podstawie komentarzem @ alessandro-Pezzato, aby uruchomić polecenia wielokrotności, po prostu użyj &, pomiędzy poleceniami.

Przykład:

$ sleep 3 & sleep 5 & sleep 2 & 

To będzie uruchomić polecenia w tle.

+0

Tego właśnie szukałem. –

+0

Wystąpił błąd, chyba że pominę ostatni znak wykrzyknika ... –

+0

Cześć @OleTange, nie znam różnicy. Próbowałem "&!" I "&" i oba działały równo. – nsantana

-5

uruchomić wiele poleceń wystarczy dodać && między dwoma poleceniami tak: command1 && command2

A jeśli chcesz uruchomić je w dwóch różnych terminali potem robisz to tak:

gnome-terminal -e "command1" && gnome-terminal -e "command2" 

Zostanie otwarte 2 terminale z command1 i command2 w nich wykonywane.

Mam nadzieję, że to pomoże.

+2

To jest nieprawidłowe. Uruchamia 'command2' ** po **' command1' i tylko wtedy, gdy 'command1' się powiedzie. Spróbuj "spać 3 i spać 3", a zobaczysz, że trwa to 6 sekund. –

+0

Komenda1 && command2 nie rozpoczyna się od razu. będzie wykonywany jeden po drugim (biorąc pod uwagę scenariusz sukcesu dla polecenia). – Gahan

Powiązane problemy