Executando milhares de processos de background curl em paralelo no script bash

14

Estou executando milhares de processos de segundo plano curl em paralelo no seguinte script 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

Eu tenho 49Gb Corei7-920 servidor dedicado (não virtual).

Eu rastreio o consumo de memória e a CPU por meio de topcomando e eles estão longe dos limites.

Estou usando ps aux | grep curl | wc -lpara contar o número de processos de curvatura atuais . Esse número aumenta rapidamente de 2 a 4 mil e depois começa a diminuir continuamente.

Se eu adicionar uma análise simples por meio de encanamento de tubulação a awk ( curl | awk > output), o número de processos de enrolamento aumentará para apenas 1-2 mil e depois diminuirá para 20-30 ...

Por que o número de processos diminui tão drasticamente? Onde estão os limites dessa arquitetura?

zavg
fonte
2
Você provavelmente está atingindo um dos limites máximos de processos em execução ou máximos soquetes abertos. ulimitmostrará alguns desses limites.
precisa saber é o seguinte
6
Também gostaria de sugerir o uso parallel(1)de tais tarefas: manpages.debian.org/cgi-bin/...
zhenech
Tente start=$SECONDSe end=$SECONDS- e use nomes de variáveis ​​em minúsculas ou em maiúsculas por hábito, a fim de evitar uma possível colisão de nomes com variáveis ​​de shell. No entanto, você realmente está apenas obtendo o intervalo de tempo cada vez maior do início de cada processo. Você não está demorando quanto tempo o download levou, pois o processo está em segundo plano (e starté calculado apenas uma vez). No Bash, você pode (( diff = end - start ))eliminar os cifrões e permitir que o espaçamento seja mais flexível. Use pgrepse você tiver.
Pausado até novo aviso.
Eu concordo com HBruijn. Observe como sua contagem de processos é reduzida pela metade quando você duplica o número de processos (adicionando awk).
Pausado até novo aviso.
@zhenech @HBrujin Lancei parallele me diz que posso executar apenas 500 tarefas paralelas devido ao limite do sistema de identificadores de arquivos. Aumentei o limite no limits.conf, mas agora, quando tento executar 5000 trabalhos simulaneus, ele consome instantaneamente toda a minha memória (49 Gb) antes mesmo do início, porque todo parallel script perl consome 32Mb.
zavg

Respostas:

12

Após a pergunta estrita:

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

Menor se você não precisar do texto padrão nos horários:

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

Se você deseja executar 1000s em paralelo, atingirá alguns limites (como identificadores de arquivo). Criar ulimit -n ou /etc/security/limits.conf pode ajudar.

Ole Tange
fonte
E se eu desejar executar vários comandos como o da versão de resposta curta em paralelo, como faço isso?
Guy Avraham
2
Citá-lo: seq 100 | parallel 'echo here is command 1: {}; echo here is command 2: {}'. Passe uma hora percorrendo o tutorial. Sua linha de comando o amará por isso:man parallel_tutorial
Ole Tange
2
for i in {1..100000}

Existem apenas 65536 portas. Acelere isso.

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

(edit: (edit: tira afirmação severamente datada sobre os limites do SO e adiciona o que falta )echocurl
wait

jthill
fonte
Na verdade, o sistema operacional pode lidar com isso muito bem. Esta é uma limitação do TCP. Nenhum sistema operacional, por mais especial que seja, será capaz de contorná-lo. Mas 4k conexões do OP está longe de 64k (ou a 32k padrão de algumas distros)
Patrick
@ Patrick bem, eu tirei essa parte, é redundante com um limite de design irrecuperável, mas veja o comentário de zavg no dia 7.
jthill