Come impedire agli xargs di fondere male l'output di più processi?


17

Sto usando xargscon l'opzione --max-args=0(in alternativa -P 0).

Tuttavia, l'output dei processi viene unito al stdoutflusso senza tener conto della corretta separazione delle linee. Quindi finirò spesso con linee come:

<start-of-line-1><line-2><end-of-line-1>

Come sto usando egrepcon ^nel mio modello sull'intero xargsoutput, questo sta rovinando il mio risultato.

Esiste un modo per forzare la xargsscrittura degli output del processo in ordine (qualsiasi ordine, purché l'output di un processo sia contiguo)?

O qualche altra soluzione?

Modifica: maggiori dettagli sul caso d'uso:

Voglio scaricare e analizzare pagine Web da host diversi. Poiché ogni pagina impiega circa un secondo per caricarsi e ci sono alcune decine di pagine che voglio parallelizzare le richieste.

Il mio comando ha la forma seguente:

echo -n $IPs | xargs --max-args=1 -I {} --delimiter ' ' --max-procs=0 \
wget -q -O- http://{}/somepage.html | egrep --count '^string'

Uso bash e non qualcosa come Perl perché gli IP host (la variabile $ IPs) e alcuni altri dati provengono da un file bash incluso.


Puoi dare un esempio più completo alla tua domanda? Non è chiaro come o perché si stia attualmente utilizzando xargs.
Caleb,

La soluzione sarà dura, è necessario utilizzare descrittori di file diversi per gli stdout di ogni processo e utilizzare un piccolo server per raccogliere le linee. xargsnon sembra fornire tale funzionalità.
Stéphane Gimenez,

@Caleb Ecco, spero che questo aiuti :-)
Christoph Wurm,

Sicuramente non è una soluzione leggera, ma forse potresti usare makela funzione dei lavori, penso che makeunisca correttamente le linee di output.
Stéphane Gimenez,

aggiunge la --line-bufferedbandiera per egrepaiutare
iruvar

Risposte:


6

Questo dovrebbe fare il trucco:

echo -n $IPs | xargs --max-args=1 -I {} --delimiter ' ' --max-procs=0 \
  sh -c "wget -q -O- 'http://{}/somepage.html' | egrep --count '^string'" | \
  { NUM=0; while read i; do NUM=$(($NUM + $i)); done; echo $NUM; }

L'idea qui è di fare conteggi separati e sommarli alla fine. Potrebbe fallire se i conteggi separati sono abbastanza grandi da essere mescolati, ma non dovrebbe essere così.


14

GNU Parallel è progettato specificatamente per risolvere questo problema:

echo -n $IPs | parallel -d ' ' -j0 wget -q -O- http://{}/somepage.html | egrep --count '^string'

Se i tuoi IP sono in un file, è ancora più bello:

cat IPs | parallel -j0 wget -q -O- http://{}/somepage.html | egrep --count '^string'

Per saperne di più guarda il video introduttivo: http://www.youtube.com/watch?v=OpaiGYxkSuQ


2
Strumento carino! Inoltre, scommetto che qualcuno ti dirà che il gatto è inutile molto presto.
Stéphane Gimenez,

1
Lo so. Ma trovo più facile da leggere e di solito lavoro su 48 macchine core, quindi i pochi cicli di clock extra per uno dei core inattivi devono ancora essere un problema.
Ole Tange,

parallelo sarebbe perfetto per il lavoro se fosse nei repository Debian.
Christoph Wurm,

1
@Legate Debian include il parallelcomando di moreutils , che è sufficiente qui:parallel -j99 -i sh -c 'wget -q -O- http://{}/somepage.html | egrep -c "^string"' -- $IPs
Gilles

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.