Як зупинити xargs від погано злитого виходу з декількох процесів?


18

Я використовую xargsваріант --max-args=0(альтернативно -P 0).

Однак вихід процесів об'єднується в stdoutпотік, не враховуючи належного розділення лінії. Тому я часто стикаюся з такими рядками, як:

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

Як я використовую egrepз ^в моєму шаблоні на всій xargsпродукції цього Мессінг мій результат.

Чи є якийсь спосіб змусити xargsзаписувати результати виводу в порядку (будь-який порядок, якщо вихід одного процесу суміжний)?

Або якесь інше рішення?

Редагувати: детальніше про випадок використання:

Я хочу завантажити та проаналізувати веб-сторінки з різних хостів. Оскільки для завантаження кожної сторінки потрібно близько секунди, і я хочу паралелізувати запити на кілька десятків сторінок.

Моя команда має таку форму:

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

Я використовую bash, а не щось на зразок Perl, оскільки IP-адреси хоста (змінна $ IPs) та деякі інші дані надходять із включеного файлу bash.


Чи можете ви зробити більш повний приклад свого питання? Незрозуміло, як і чому ви зараз користуєтесь xargs.
Калеб

Рішення цього буде важким, потрібно використовувати різні дескриптори файлів для stdout кожного процесу і використовувати невеликий сервер для збору рядків. xargsсхоже, не надає такої функції.
Стефан Гіменез

@Caleb Там, сподіваюся, це допоможе :-)
Крістоф Вурм

Однозначно не легке рішення, але, можливо, ви можете використовувати makeфункцію робочих місць, я думаю, що makeоб'єднує вихідні лінії належним чином.
Стефан Гіменез

додає --line-bufferedпрапор на egrepдопомогу
iruvar

Відповіді:


6

Для цього слід зробити фокус:

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

Ідея тут - зробити окремі підрахунки та підсумовувати їх наприкінці. Можливо, не вдасться, якщо окремі підрахунки досить великі, щоб їх змішати, але це не повинно бути так.


14

GNU Parallel спеціально розроблений для вирішення цієї проблеми:

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

Якщо ваші IP-адреси є у файлі, це ще красивіше:

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

Щоб дізнатися більше, перегляньте вступне відео: http://www.youtube.com/watch?v=OpaiGYxkSuQ


2
Гарний інструмент! Крім того, я ставлю на облік, що хтось скаже вам, що кот дуже скоро марний.
Stéphane Gimenez

1
Я знаю. Але мені легше читати, і я зазвичай працюю на 48 основних машинах, тому кілька додаткових тактових циклів для одного з непрацюючих ядер все ще не є проблемою.
Оле Танге

паралель була б ідеальною для роботи, якби вона знаходилася в сховищах Debian.
Крістоф Вурм

1
@Legate Debian включає в себе parallelкоманду moreutils , якої тут достатньо:parallel -j99 -i sh -c 'wget -q -O- http://{}/somepage.html | egrep -c "^string"' -- $IPs
Жил "SO- перестань бути злим"

@Legate checkout build.opensuse.org/package/… для .deb-файлу та bugs.debian.org/cgi-bin/bugreport.cgi?bug=518696 для помилки.
Оле Танге
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.