Как остановить xargs от плохого слияния вывода из нескольких процессов?


17

Я использую 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.
Калеб

Решение этой проблемы будет непростым: необходимо использовать разные файловые дескрипторы для вывода каждого процесса и использовать небольшой сервер для сбора строк. 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
Хороший инструмент! Кроме того, я держу пари, что кто-то скажет вам, что кошка очень бесполезна очень скоро.
Стефан Гименес

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

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

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

@Legate фотографии 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.