Jak powstrzymać xargs przed złym łączeniem danych wyjściowych z wielu procesów?


17

Używam xargsz opcją --max-args=0(alternatywnie -P 0).

Jednak wyniki procesów są scalane ze stdoutstrumieniem bez uwzględnienia właściwego rozdzielenia linii. Więc często kończę liniami takimi jak:

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

Ponieważ używam egrepz ^moim wzorem na całej xargswyjście to jest brudząc się mój wynik.

Czy jest jakiś sposób na wymuszenie xargszapisu wyników procesu w dowolnej kolejności (w dowolnej kolejności, o ile wynik jednego procesu jest ciągły)?

Lub jakieś inne rozwiązanie?

Edycja: więcej szczegółów na temat przypadku użycia:

Chcę pobierać i analizować strony internetowe z różnych hostów. Ponieważ ładowanie każdej strony zajmuje około sekundy, a istnieje kilkadziesiąt stron, chcę zrównoważyć żądania.

Moje polecenie ma następującą postać:

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

Używam bash, a nie czegoś takiego jak Perl, ponieważ adresy IP hosta (zmienna $ IPs) i niektóre inne dane pochodzą z dołączonego pliku bash.


Czy możesz podać pełniejszy przykład swojego pytania? Nie jest jasne, w jaki sposób i dlaczego obecnie używasz xargs.
Caleb

Rozwiązanie tego będzie trudne, należy użyć różnych deskryptorów plików dla standardowych parametrów każdego procesu i użyć małego serwera do zebrania linii. xargsnie wydaje się zapewniać takiej funkcji.
Stéphane Gimenez

@Caleb Proszę bardzo, mam nadzieję, że to pomoże :-)
Christoph Wurm

Zdecydowanie nie jest to lekkie rozwiązanie, ale być może warto skorzystać makez funkcji zadań, myślę, że odpowiednio makełączy linie wyjściowe.
Stéphane Gimenez

dodaje --line-bufferedflagę, aby egreppomóc
iruvar,

Odpowiedzi:


6

To powinno załatwić sprawę:

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; }

Chodzi o to, aby osobno policzyć i zsumować je na końcu. Może się nie powieść, jeśli osobne liczby są wystarczająco duże, aby je pomieszać, ale nie powinno tak być.


14

GNU Parallel jest specjalnie zaprojektowany, aby rozwiązać ten problem:

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

Jeśli twoje adresy IP znajdują się w pliku, jest jeszcze ładniejsze:

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

Aby dowiedzieć się więcej, obejrzyj wideo wprowadzające: http://www.youtube.com/watch?v=OpaiGYxkSuQ


2
Ładne narzędzie! Założę się też, że ktoś powie ci wkrótce, że kot jest bezużyteczny.
Stéphane Gimenez

1
Wiem. Ale łatwiej mi to czytać i zwykle pracuję na 48 rdzeniach, więc kilka dodatkowych cykli zegara dla jednego z wolnych rdzeni wciąż musi stanowić problem.
Ole Tange

Równoległość byłaby idealna do pracy, gdyby była w repozytoriach Debiana.
Christoph Wurm

1
@Legate Debian zawiera parallelpolecenie z moreutils , które jest wystarczające tutaj:parallel -j99 -i sh -c 'wget -q -O- http://{}/somepage.html | egrep -c "^string"' -- $IPs
Gilles 'SO- przestań być zły'

@ Legate Checkout build.opensuse.org/package/… dla pliku .deb i bugs.debian.org/cgi-bin/bugreport.cgi?bug=518696 dla błędu do wypchnięcia.
Ole Tange
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.