Hitung jumlah byte yang disalurkan dari satu proses ke proses lainnya

17

Saya menjalankan skrip shell yang menyalurkan data dari satu proses ke proses lainnya

process_a | process_b

Apakah ada yang tahu cara untuk mengetahui berapa banyak byte yang dilewatkan antara kedua program? Satu-satunya solusi yang dapat saya pikirkan saat ini adalah menulis sebuah program c kecil yang bertuliskan stdin, menulis ke stdout dan menghitung semua data yang ditransfer, menyimpan hitungan dalam variabel lingkungan, seperti:

process_a | count_bytes | process_b

Adakah yang punya solusi yang lebih rapi?

Simon Hodgson
sumber

Jawaban:

16

Pipa melalui dd. Input default dd adalah stdin dan output default adalah stdout; ketika selesai stdin / stdout I / O, itu akan melaporkan ke stderr tentang berapa banyak data yang ditransfer.

Jika Anda ingin menangkap output dari dd dan program lain sudah berbicara dengan stderr, maka gunakan deskriptor file lain. Misalnya,

$ exec 4>~/fred
$ input-command | dd 2>&4 | output-command
$ exec 4>&-
Phil P
sumber
2
Tidak bisakah Anda melewatkan execdan langsung menampilkan ke file? input-command | dd 2>~/fred | output-command
Dijeda sampai pemberitahuan lebih lanjut.
2
Ya, ya. Rupanya aku mengalami salah satu momen "itu", maaf.
Phil P
28

Gunakan pv penampil pipa. Ini alat yang hebat. Setelah Anda mengetahuinya, Anda tidak akan pernah tahu bagaimana Anda hidup tanpanya.

Ini juga dapat menunjukkan kepada Anda bilah kemajuan, dan 'kecepatan' transfer.

Rory
sumber
Dalam pencarian saya, saya telah menemukan ini, tapi saya membutuhkannya untuk mengatur variabel dengan jumlah byte yang ditransfer sehingga saya dapat menggunakannya dalam proses lain.
Simon Hodgson
Contoh penggunaan: cat file | pv -bakan mengembalikan ukuran file.
rodorgas
6

process_a | tee >(process_b) | wc --bytesmungkin bekerja. Anda kemudian dapat mengarahkan ulang wchitungan ke mana pun Anda membutuhkannya. Jika process_boutput apa pun ke stdout/ stderrAnda mungkin perlu mengarahkan ini di suatu tempat, jika saja /dev/null.

Untuk contoh yang sedikit dibuat-buat:

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

Sebagai penjelasan: teememungkinkan Anda mengarahkan keluaran ke banyak file (plus stdout) dan >()konstruksinya adalah "proses substitusi" bash yang membuat proses tampak seperti file hanya-tulis dalam kasus ini sehingga Anda dapat mengarahkan ulang ke proses serta file ( lihat di sini , atau pertanyaan + jawaban ini untuk contoh penggunaan teeuntuk mengirim output ke banyak proses).

David Spillett
sumber
Saya suka solusi ini, sayangnya shelll yang saya gunakan (BusyBox) tampaknya tidak mendukung notasi> (), tetapi ia memberikan cara untuk melakukan apa yang saya cari.
Simon Hodgson
Ya, Anda memerlukan bash yang cukup lengkap untuk memiliki fitur itu - itu adalah jenis hal yang tidak biasa digunakan sehingga dihilangkan dari shell yang dapat dipotong (bahkan yang dengan target menjadi bash yang lebih atau kurang kompatibel) seperti busybox untuk menghemat ruang.
David Spillett
1

Saya tahu saya terlambat ke pesta, tapi saya yakin saya punya jawaban yang bagus yang dapat meningkatkan utas bermanfaat ini.
Ini adalah campuran dari @Phil P dan @David Spillett jawaban, tetapi:

  • berbeda dengan @Phil P, ia menghindari membuat file baru
  • berbeda dari @ David Spillett, itu mempertahankan struktur pipa

Bytes-count dicetak ke stdout, bersama dengan output dari process_b.
Anda dapat menggunakan awalan untuk mengidentifikasi baris yang berisi byte saat bekerja dengan output ( Bytes:dalam contoh).

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

PERINGATAN:
Jangan bergantung pada urutan garis dalam output
. Urutan tidak dapat diprediksi dan selalu dapat berbeda, bahkan ketika memanggil skrip yang sama dengan parameter yang sama!

Claudio
sumber
Sayangnya, ini masih merupakan konstruksi bash-only ...
Mikhail T.