A saída é misturada assim por causa dos xargs e como posso consertá-la?

3

Estou aprendendo um pouco de Bash usando xargs para listar registros whois para um monte de endereços IP. O comando usado é:

echo "$1" | tr "\n" "
sh -c echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net 206.190.36.45 ; echo "\n 44rEnd whois record -- \n"
sh -c echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net 212.146.69.237 ; echo "\n 44rEnd whois record -- \n"
sh -c echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net 77.238.184.24 ; echo "\n 44rEnd whois record -- \n"
" | xargs -0 -n 1 -t -P 3 -I % sh -c 'echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net % ; echo "\n 44rEnd whois record -- \n"'

Os comandos executados são:

44rBegin whois record

44rBegin whois record

44rBegin whois record

whois1 output

44rEnd whois record --

whois2 output

44rEnd whois record --

whois3 output

44rEnd whois record --

Eu quero que a saída apareça como se cada bloco de comandos executado usando sh -c fosse executado sequencialmente. Em vez disso, minha saída é algo como:

echo "$1" | tr "\n" "
sh -c echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net 206.190.36.45 ; echo "\n 44rEnd whois record -- \n"
sh -c echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net 212.146.69.237 ; echo "\n 44rEnd whois record -- \n"
sh -c echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net 77.238.184.24 ; echo "\n 44rEnd whois record -- \n"
" | xargs -0 -n 1 -t -P 3 -I % sh -c 'echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net % ; echo "\n 44rEnd whois record -- \n"'

Como posso resolver este problema?

    
por tubis 11.07.2014 / 17:50

3 respostas

2

Sempre que você tem vários processos saindo para o mesmo terminal (ou arquivo) em paralelo, você corre o risco de sua saída ficar intercalada (a menos que você organize algum tipo de bloqueio ou use chamadas de sistema de baixo nível como write para arquivos abertos no modo somente anexo).

Como primeiro passo, você pode minimizar, mas não eliminar totalmente, o problema fazendo com que cada invocação de shell use substituição de comando : execute o comando whois como um subprocesso, capturando sua saída e, em seguida, imprima tudo que foi combinado em uma operação printf .

xargs -0 -n 1 -P 3 -I %% sh -c 'printf "\n%s\n%s\n%s\n" " 44rBegin whois record -- " "$(whois -h whois.arin.net %%)" " 44rEnd whois record -- "'

Melhor ainda, se você tiver o programa flock disponível, poderá usá-lo para bloquear cada chamada para esse printf :

combinado
xargs -0 -n 1 -P 3 -I %% sh -c 'who="$(whois -h whois.arin.net %%)"; flock /tmp/who.lock printf "\n%s\n%s\n%s\n" " 44rBegin whois record -- " "$who" " 44rEnd whois record -- "'
    
por 11.07.2014 / 19:58
6

Neste caso específico, você está passando -P 3 para xargs .

   -P max-procs
          Run up to max-procs processes at a time; the default is 1.  If max-procs  is
          0,  xargs  will run as many processes as possible at a time.  Use the -n op‐
          tion with -P; otherwise chances are that only one exec will be done.

Porque você os está executando em paralelo, todos vão escrever suas saídas ao mesmo tempo.

Se você copiou este comando de outro lugar, recomendo que você pesquise para entender o que está copiando. Fazer o contrário pode ser perigoso.

    
por 11.07.2014 / 18:05
2

Sim, a saída é mista devido a xargs -P . Você está executando vários subprocessos em paralelo, e não há nada para coordenar sua saída: eles estão todos escrevendo a saída sempre que querem e tudo fica confuso.

Use o GNU Parallel , que é uma ferramenta muito mais poderosa para fazer o mesmo trabalho que xargs -P . Seu padrão é agrupar os resultados de cada trabalho juntos .

echo "$1" | parallel -t -P 3 sh -c 'echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net $0; echo "\n 44rEnd whois record -- \n"'
    
por 13.07.2014 / 02:33