tar ke pipa tetapi tetap -v keluaran verbose terpisah dari STDERR

12

Perintah tar normal

tar cvf foo.tar ./foo >foo.out 2>foo.err

memiliki tiga aliran IO output

  • arsipkan data ke foo.tar
  • daftar nama file ke STDOUT (dialihkan ke foo.out)
  • pesan kesalahan ke STDERR (dialihkan ke foo.err)

Saya kemudian dapat memeriksa foo.err untuk pesan kesalahan tanpa harus membaca daftar nama file.

jika saya ingin melakukan sesuatu dengan data arsip (pipa melalui netcat atau program kompresi khusus) saya dapat menggunakan -f -opsi tar dengan demikian

tar cvf - ./foo 2>foo.err | squish > foo.tar.S

Tapi sekarang daftar nama file saya dicampur dengan pesan kesalahan saya karena -voutput tar jelas tidak bisa pergi ke STDOUT (di situlah data arsip mengalir) jadi tar dengan cerdik menulisnya ke STDERR sebagai gantinya.

Menggunakan Korn shell, apakah ada cara untuk membangun perintah yang menyalurkan aliran arsip ke perintah lain tetapi masih menangkap -voutput secara terpisah dari pesan kesalahan apa pun.

RedGrittyBrick
sumber
Apakah Anda kenal tee? Ini sepertinya kasus penggunaan yang cukup valid untuk itu.
HalosGhost

Jawaban:

9

Jika sistem Anda mendukung /dev/fd/n:

tar cvf /dev/fd/3 ./foo 3>&1 > foo.out 2>foo.err | squish > foo.tar.S

Yang dengan implementasi AT&T ksh( bashatau zsh) Anda dapat menulis menggunakan subtitusi proses :

tar cvf >(squish > foo.tar.S) ./foo > foo.out 2>foo.err

Itu melakukan hal yang persis sama kecuali bahwa kali ini, shell memutuskan deskriptor file mana yang akan digunakan 3(biasanya di atas 9). Perbedaan lainnya adalah bahwa kali ini, Anda mendapatkan status keluar taralih-alih squish. Pada sistem yang tidak mendukung /dev/fd/n, beberapa shell mungkin menggunakan pipa bernama untuk fitur itu.

Jika sistem Anda tidak mendukung /dev/fd/natau shell Anda tidak dapat menggunakan pipa bernama untuk substitusi prosesnya, di situlah Anda harus berurusan dengan pipa bernama dengan tangan .

Stéphane Chazelas
sumber
6

Anda harus menggunakan pipa bernama untuk itu.

Pertama buat satu di folder:

mkfifo foo.pipe

Kemudian gunakan perintah itu:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & cat foo.pipe >foo.tar

Pemberitahuan: yang cat-bagian, sekarang dapat juga menjadi gzipatau apa pun, yang dapat membaca dari pipa:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & gzip -c foo.pipe >foo.tar

Penjelasan:

Output ditulis ke pipa nama ( foo.pipe), di mana proccess lain ( cat, gzip, netcat) membaca dari. Jadi Anda tidak kehilangan saluran stdout / stderr untuk mendapatkan informasi.

kekacauan
sumber
1
Mungkin patut dicatat implikasi menggunakan pipa bernama . 1) yang terbaik adalah mengatur umask 077(atau menggunakan dir temp pribadi) untuk mencegah proses lain membaca atau menulis untuk itu (pada banyak sistem, pipa bernama, seperti file lain yang dibuat dapat dibaca dunia secara default), 2) Anda perlu memastikan pipa bernama hanya digunakan oleh setiap instance skrip Anda (sekali lagi direktori sementara pribadi membantu) 3) Itu berarti Anda perlu membersihkan setelahnya atau jika terganggu.
Stéphane Chazelas
1
+1 - Saya suka jawaban ini. Sayangnya bagi saya, ada beberapa keanehan dalam pipa bernama pada sistem saya (lama) yang membuat mereka tidak dapat diandalkan ketika saya mencoba ini.
RedGrittyBrick
1
@ StéphaneChazelas - Saya pikir kadang-kadang bisa lebih mudah untuk dibersihkan terlebih dahulu, seperti:p="/tmp/pipe$$"; mkfifo "$p"; (read na; cmd[s]...) <>"$p" & (echo;rm "$p"; cmd[s]...) >"$p"
mikeserv
5

--index-fileOpsi tar GNU berfungsi dengan baik:

tar cvf - ./foo 2>foo.err --index-file=foo.out | squish > foo.tar.S
Josh Kelley
sumber