Подсчитать количество байтов, переданных от одного процесса другому

17

Я запускаю сценарий оболочки, который передает данные от одного процесса к другому

process_a | process_b

Кто-нибудь знает способ узнать, сколько байтов было передано между двумя программами? Единственное решение, которое я могу придумать на данный момент, - написать небольшую программу на c, которая читает из stdin, записывает в stdout и подсчитывает все переданные данные, сохраняя счет в переменной окружения, например:

process_a | count_bytes | process_b

У кого-нибудь есть более аккуратное решение?

Саймон Ходжсон
источник

Ответы:

16

Труба через дд. ввод по умолчанию для dd - это stdin, а вывод по умолчанию - для stdout; когда он завершает ввод-вывод stdin / stdout, он сообщает stderr, сколько данных он передал.

Если вы хотите захватить вывод dd, а другие программы уже общаются со stderr, используйте другой дескриптор файла. Например,

$ exec 4>~/fred
$ input-command | dd 2>&4 | output-command
$ exec 4>&-
Фил П
источник
2
Не могли бы вы пропустить execи просто вывести в файл напрямую? input-command | dd 2>~/fred | output-command
Приостановлено до дальнейшего уведомления.
2
О да. Видимо, у меня был один из "тех" моментов, извините.
Фил П
28

Используйте pv the pipe viewer. Это отличный инструмент. Когда вы узнаете об этом, вы никогда не узнаете, как вы жили без него.

Он также может показать вам индикатор выполнения и «скорость» передачи.

Рори
источник
В моем поиске я столкнулся с этим, но мне нужно установить переменную с количеством переданных байтов, чтобы я мог использовать ее в другом процессе.
Саймон Ходжсон
Пример использования: cat file | pv -bвернет размер файла.
Родоргас
6

process_a | tee >(process_b) | wc --bytesможет работать. Затем вы можете перенаправить wcсчет туда, где он вам нужен. Если что-то process_bвыводит в stdout/ stderrвам, вероятно, нужно будет куда-то перенаправить это, если только /dev/null.

Для слегка надуманного примера:

filestore:~# cat document.odt | tee >(dd of=/dev/null 2>/dev/null) | wc --bytes
4295

В качестве объяснения: teeпозволяет вам направлять вывод в несколько файлов (плюс стандартный вывод), а >()конструкция является «заменой процесса» в bash, которая в этом случае делает процесс похожим на файл только для записи, так что вы можете перенаправить на процессы, а также на файлы ( см. здесь или этот вопрос + ответ для примера использования teeдля отправки вывода во многие процессы).

Дэвид Спиллетт
источник
Мне нравится это решение, к сожалению, оболочка, которую я использую (BusyBox), по-видимому, не поддерживает нотацию> (), но она предоставляет способ сделать то, что мне нужно.
Саймон Ходжсон
Да, вам нужна довольно полная версия bash, чтобы иметь эту функцию - это тот тип вещей, который обычно не используется, поэтому его вырезают из урезанных оболочек (даже тех, для которых цель более или менее совместима с bash) как busybox для экономии места.
Дэвид Спиллетт
1

Я знаю, что опаздываю на вечеринку, но я думаю, что у меня есть хороший ответ, который может улучшить эту полезную тему.
Это сочетание @Phil P и @David Spillett ответа, но:

  • в отличие от @Phil P, он избегает создания нового файла
  • в отличие от @David Spillett, он поддерживает структуру конвейера

Число байтов выводится в стандартный вывод вместе с любым выводом процесса process_b.
Вы можете использовать префикс для идентификации строки, содержащей байты, при работе с выводом ( Bytes:в примере).

exec 3>&1
process_a | tee >({ echo -n 'Bytes:'; wc -c; } >&3) | process_b
exec 3>&-

ВНИМАНИЕ:
Не полагайтесь на порядок строк в выходных данных
. Порядок непредсказуем и всегда может отличаться даже при вызове одного и того же сценария с одинаковыми параметрами!

Claudio
источник
К сожалению, это все еще конструкция только для bash ...
Михаил Т.