Uruchom polecenia równolegle i poczekaj, aż jedna grupa poleceń zakończy działanie, zanim zaczniesz następną

12

Mam skrypt zawierający wiele poleceń. Jak grupować polecenia, aby działały razem (chcę utworzyć kilka grup poleceń. W obrębie każdej grupy polecenia powinny być uruchamiane równolegle (jednocześnie). Grupy powinny działać sekwencyjnie, czekając na zakończenie jednej grupy przed rozpoczęciem następna grupa) ... tj

#!/bin/bash
command #1
command #2
command #3
command #4
command #5
command #6
command #7
command #8
command #9
command #10

jak mogę uruchamiać co 3 polecenia, aby się zebrać? Próbowałem:

#!/bin/bash
{
command #1
command #2
command #3
} & 
{   
command #4
command #5
command #6
} & 
{
command #7
command #8
command #9
}&
command #10

Ale to nie działało poprawnie (chcę równolegle uruchamiać grupy poleceń. Muszę też poczekać, aż pierwsza grupa się zakończy, zanim uruchomię następną grupę)

Skrypt kończy działanie z komunikatem o błędzie!

RobertL
źródło
2
Co masz na myśli, biegnijcie razem. Masz na myśli bieganie równolegle w tym samym czasie? Skąd wiesz, że „nie działało poprawnie?” Skąd będziesz wiedzieć, kiedy to działa poprawnie? Czy chcesz poczekać na zakończenie pierwszej grupy przed uruchomieniem kolejnej grupy?
RobertL
@ RobertL. Tak, mam na myśli równolegle w tym samym czasie. Skrypt kończy działanie z komunikatem o błędzie. Tak, muszę poczekać na zakończenie pierwszej grupy przed uruchomieniem następnej grupy.
1
@ goro cytuje cię, skrypt wychodzi z komunikatem o błędzie. Zmodyfikuj swoje pytanie, aby dodać taką wiadomość (ze względu na zakończenie) i usuń czat-czat ​​(mile widziane porady).
dave_alcarin
Czy to samo polecenie działa w każdej instancji? Takie samo imię?
RobertL,
1
@goro, Czy to jest dokładne? „Masz kilka grup poleceń. W obrębie każdej grupy polecenia powinny być uruchamiane równolegle (jednocześnie). Grupy powinny działać sekwencyjnie, czekając na zakończenie jednej grupy przed rozpoczęciem następnej grupy.”
RobertL,

Odpowiedzi:

20

Polecenia w obrębie każdej grupy działają równolegle, a grupy działają kolejno, każda grupa poleceń równoległych czeka na zakończenie poprzedniej grupy przed rozpoczęciem wykonywania.

Oto działający przykład:

Załóż 3 grupy poleceń jak w poniższym kodzie. W każdej grupie trzy polecenia są uruchamiane w tle za pomocą &.

3 polecenia zostaną uruchomione prawie w tym samym czasie i będą działać równolegle, dopóki skrypt waitsich nie zakończy.

Po wykonaniu wszystkich trzech poleceń w trzeciej grupie, command 10zostanie wykonane.

$ cat command_groups.sh 
#!/bin/sh

command() {
    echo $1 start
    sleep $(( $1 & 03 ))      # keep the seconds value within 0-3
    echo $1 complete
}

echo First Group:
command 1 &
command 2 &
command 3 &
wait

echo Second Group:
command 4 &
command 5 &
command 6 &
wait

echo Third Group:
command 7 &
command 8 &
command 9 &
wait

echo Not really a group, no need for background/wait:
command 10

$ sh command_groups.sh 
First Group:
1 start
2 start
3 start
1 complete
2 complete
3 complete
Second Group:
4 start
5 start
6 start
4 complete
5 complete
6 complete
Third Group:
7 start
8 start
9 start
8 complete
9 complete
7 complete
Not really a group, no need for background/wait:
10 start
10 complete
$   
RobertL
źródło
Myślę jednak, że curlies są całkowicie bez znaczenia w twoim przykładzie. Oczekiwanie jest procesem globalnym, a zwinięte grupy nie utworzą w tym przypadku nowego rozwidlenia.
PSkocik,
1
@PSkocik, True. Narządy szczątkowe.
RobertL,
6
{
command #1
command #2
command #3
} & 
{   
command #4
command #5
command #6
} & 
{
command #7
command #8
command #9
}&
command #10
wait #<===

Powinien działać (każdy pojedynczy komponent trypletu będzie działał sekwencyjnie, ale grupy hete będą działały równolegle). Prawdopodobnie nie chcesz, aby twoja powłoka nadrzędna zakończyła się przed zakończeniem grup - stąd wait.

PSkocik
źródło
2
Pierwotne pytanie brzmiało: „uruchamiaj co 3 polecenia razem”. Bez wyjaśnienia, każda odpowiedź jest poprawna. Dobre połączenie z wait.
RobertL,