Równoległe uruchamianie tysięcy procesów zwijania w tle w skrypcie bash

14

Korzystam z tysięcy procesów zwijania w tle równolegle w następującym skrypcie bash

START=$(date +%s)
for i in {1..100000}
do       
    curl -s "http://some_url_here/"$i  > $i.txt&
    END=$(date +%s)
    DIFF=$(( $END - $START ))
    echo "It took $DIFF seconds"
done

Mam serwer dedykowany 49Gb Corei7-920 (nie wirtualny).

Śledzę zużycie pamięci i procesora za pomocą toppoleceń i są one daleko od granic.

Używam ps aux | grep curl | wc -ldo zliczania liczby bieżących procesów zwijania . Liczba ta rośnie gwałtownie do 2-4 tysięcy, a następnie zaczyna się stale zmniejszać.

Jeśli dodam proste analizowanie przez zawijanie rur do awk ( curl | awk > output), wówczas liczba procesów zwijania wzrośnie tylko do 1-2 tysięcy, a następnie spadnie do 20-30 ...

Dlaczego liczba procesów spada tak gwałtownie? Gdzie są granice tej architektury?

zavg
źródło
2
Prawdopodobnie osiągasz limit maksymalnej liczby uruchomionych procesów lub maksymalnej liczby otwartych gniazd. ulimitpokaże niektóre z tych limitów.
HBruijn,
6
Ja też sugerowałoby używając parallel(1)do takich zadań: manpages.debian.org/cgi-bin/...
zhenech
Spróbuj start=$SECONDSi end=$SECONDS- i używaj nazw zmiennych o małych i małych literach według przyzwyczajenia, aby uniknąć potencjalnej kolizji nazw ze zmiennymi powłoki. Jednak tak naprawdę otrzymujesz tylko coraz większy przedział czasu na początku każdego procesu. Nie masz pojęcia, ile czasu trwało pobieranie, ponieważ proces jest w tle (i startjest obliczany tylko raz). W Bash możesz (( diff = end - start ))upuścić znaki dolara i pozwolić, aby odstępy były bardziej elastyczne. Użyj, pgrepjeśli go masz.
Wstrzymano do odwołania.
Zgadzam się z HBruijn. Zauważ, że liczba procesów zmniejszyła się o połowę, kiedy podwoisz liczbę procesów (przez dodanie awk).
Wstrzymano do odwołania.
@zhenech @HBrujin Uruchomiłem paralleli mówi mi, że mogę wykonywać tylko 500 równoległych zadań z powodu ograniczeń systemowych uchwytów plików. Podniosłem limit w limit.conf, ale teraz, gdy próbuję uruchomić 5000 zadań Simulaneus, natychmiast zjada całą moją pamięć (49 Gb), nawet przed uruchomieniem, ponieważ każdy parallel skrypt perla zjada 32Mb.
zavg

Odpowiedzi:

12

Po ścisłym pytaniu:

mycurl() {
    START=$(date +%s)
    curl -s "http://some_url_here/"$1  > $1.txt
    END=$(date +%s)
    DIFF=$(( $END - $START ))
    echo "It took $DIFF seconds"
}
export -f mycurl

seq 100000 | parallel -j0 mycurl

Krótszy, jeśli nie potrzebujesz tekstu płyty głównej wokół czasów:

seq 100000 | parallel -j0 --joblog log curl -s http://some_url_here/{} ">" {}.txt
cut -f 4 log

Jeśli chcesz uruchomić 1000 równolegle, osiągniesz pewne ograniczenia (takie jak uchwyty plików). Podnoszenie ulimit -n lub /etc/security/limits.conf może pomóc.

Ole Tange
źródło
A jeśli chcę równolegle uruchamiać kilka poleceń jak w krótkiej wersji odpowiedzi, jak to zrobić?
Guy Avraham,
2
Cytując go: seq 100 | parallel 'echo here is command 1: {}; echo here is command 2: {}'. Poświęć godzinę na samouczek. Twoja linia poleceń cię za to pokocha:man parallel_tutorial
Ole Tange,
2
for i in {1..100000}

Istnieje tylko 65536 portów. Ogranicz to.

for n in {1..100000..1000}; do   # start 100 fetch loops
        for i in `eval echo {$n..$((n+999))}`; do
                echo "club $i..."
                curl -s "http://some_url_here/"$i  > $i.txt
        done &
        wait
done

(edytuj: (edytuj: usuń poważnie przestarzałe stwierdzenie o limitach systemu operacyjnego i dodaj brakujące )echocurl
wait

jthill
źródło
W rzeczywistości system operacyjny może sobie z tym poradzić. Jest to ograniczenie TCP. Żaden system operacyjny, bez względu na to, jak wyjątkowy, nie będzie w stanie go obejść. Ale połączenia 4k OP nie są zbliżone do 64k (lub domyślnie 32k niektórych dystrybucji)
Patrick
@Patrick OK, wziąłem tę część, jest zbędna z nieodwracalnym limitem projektowym, ale spójrz na komentarz zavga na 7.
jthill