Jak uruchamiać równoległe procesy i łączyć wyniki, gdy oba zostaną zakończone

17

Mam skrypt powłoki bash, w którym przepuszczam dane przez około 5 lub 6 różnych programów, a następnie końcowe wyniki do pliku rozdzielanego tabulatorami.

Następnie robię to samo dla osobnego podobnego zestawu danych i wyprowadzam do drugiego pliku.

Następnie oba pliki są wprowadzane do innego programu do analizy porównawczej. np. w celu uproszczenia

Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv
AnalysisProg -i Data1res.csv Data2res.csv

Moje pytanie brzmi: w jaki sposób mogę uruchomić krok 1 i krok 2 jednocześnie (np. Używając &), ale uruchomić krok 3 (AnalysisProg) tylko wtedy, gdy oba są zakończone?

dzięki

ps AnalysisProg nie będzie działać na strumieniu lub fifo.

Stephen Henderson
źródło
BTW, czy możesz używać skryptów Perla? Może to dla ciebie bardzo uprościć i możesz bardzo skutecznie wdrożyć to przetwarzanie końcowe i sprawić, by działało ono równolegle bez wysiłku.
Bichoy
Perl ... nie tak bardzo, nie :(
Stephen Henderson
1
Tutaj pokazuję, jak podzielić dane wejściowe na potoki teei przetworzyć je za pomocą dwóch równoległych grepprocesów: unix.stackexchange.com/questions/120333/…
mikeserv
I tutaj pokazuję, jak używać prostych konstrukcji powłoki, aby w pełni proces przebiegał w sposób, który nohupmógłby, ale nadal utrzymywał sposób komunikowania się z procesem: unix.stackexchange.com/questions/121253/…
mikeserv

Odpowiedzi:

27

Zastosowanie wait. Na przykład:

Data1 ... > Data1Res.csv &
Data2 ... > Data2Res.csv &
wait
AnalysisProg

Wola:

  • uruchom potoki Data1 i Data2 jako zadania w tle
  • poczekaj, aż oba zakończą
  • uruchom AnalysisProg.

Zobacz np. To pytanie .

cxw
źródło
Dzięki, to wygląda dobrze. Spróbuję tego, jeśli powyższe nie działa.
Stephen Henderson
Jeszcze raz, byłem trochę świadomy czekania, ale po przejrzeniu google byłem trochę zmieszany, jak to działa z innym PID itp. Czuję się głupio, teraz widzę, że to po prostu „czekanie”
Stephen Henderson
12

Odpowiedź cxw jest bez wątpienia najlepszym rozwiązaniem, jeśli masz tylko 2 pliki. Jeśli 2 pliki są tylko przykładami, a w rzeczywistości masz 10000 plików, wówczas rozwiązanie „&” nie będzie działać, ponieważ spowoduje to przeciążenie serwera. Do tego potrzebujesz narzędzia takiego jak GNU Parallel:

ls Data* | parallel 'cat {} | this | that |theother | grep |sed | awk |whatever > {}res.csv
AnalysisProg -i *res.csv

Aby dowiedzieć się więcej o GNU Parallel:

Ole Tange
źródło
Cześć dzięki. W tej chwili mam dwa pliki, ale mam 24 procesory, więc miałem ochotę uruchomić wiele par naraz - choć nie jestem informatykiem, nie jestem pewien, czy warto czytać wąskie gardło na dysku. może to ssę i zobaczę;)
Stephen Henderson
@StephenHenderson w zależności od rozmiaru pliki mogą nadal znajdować się w pamięci podręcznej. Jeśli prędkość jest krytyczna, możesz po prostu użyć tmpfs (a pliki to <<<, to twoja pamięć RAM).
Maciej Piechotka
1
@StephenHenderson Liczbę równoległych zadań można dostosować za pomocą -j, więc spróbuj -j4, a jeśli serwer się nie przeciąża, spróbuj -j6 itd. Ale bądź gotowy na naciśnięcie CTRL-C: GNU Parallel jest doskonałym narzędziem do szybkiego przeciążania serwerów . Zobacz także --load.
Ole Tange
1

Jednym ze sposobów na osiągnięcie tego może być:

AnalysisProg <<PREPROCESS /dev/stdin
$( 
{   process1=$( pipe | line | 1 >&2 & echo $! )
    process2=$( pipe | line | 2 >&2 & echo $! )
    while ps -p $process1 $process2 >/dev/null; do
        sleep 1
    done
} 2>&1
)
#END
PREPROCESS

W ten sposób opieramy się na obu potokach, ale nadal czekamy, aż zakończą działanie, zanim połączą swoje wyjście w stdin, które jest analizowane w niniejszym dokumencie i przekazywane do AnalysisProg. Jeśli możesz waittego użyć, jest to nawet lepsze niż while pspętla, ale w zależności od powłoki waitmożesz sprzeciwić się, jeśli poinstruujesz ją, aby poczekał na proces, który nie jest potomkiem bieżącej powłoki.

Zauważ też, że powyższa metoda zestawi dane wyjściowe - więc oba procesy będą zapisywane jednocześnie. Jeśli zamiast tego chciałbyś, aby były one oddzielone lub dołączone do siebie, możesz zrobić:

AnalysisProg 3<<PREPROCESS /dev/fd/3 /dev/stderr
$(
process1=$(... >&2 ...) 2>/dev/fd/3
...
} 3>/dev/fd/3 2>/dev/stderr
)

Pokazałem już te koncepcje. Prawdopodobnie najlepsze dema są tu i tutaj .

mikeserv
źródło
0

Spróbuj tego użyć.

rm -f Data1Res.csv
rm -f Data2Res.csv
Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv &
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv &
while true
do
  ps aux | grep -v grep | grep -i -E 'Data1Res.csv|Data2Res.csv' &> /dev/null
  if [ $? -ne 0 ]
  then
    AnalysisProg -i Data1res.csv Data2res.csv
    exit 0
  fi
done
Renan Vicente
źródło
Cóż, to ciężkie. Czy to nie jest jak wynalezienie waitkoła?
John WH Smith