Bagaimana cara mengarahkan stdout dan stderr ke file dan menampilkan stderr ke konsol?


18

Saya tahu cara mengarahkan ke file, dan menggunakan tee; pada tingkat dasar. Begitu

$ alias outanderr='bash -c "echo stdout >&1; echo stderr >&2"'
# A fake "application" displaying both output and error messages.

$ outanderr 1>file      # redirect stdout to a file, display stderr
stderr

$ outanderr 2>file      # redirect stderr to a file, display stdout
stdout

$ outanderr 1>file 2>&1 # redirect both to a file, display nothing

$ outanderr | tee file; echo "-- file contents --" && cat file
# redirect stdout to a file, display both (note: order is messed up)
stderr
stdout
-- file contents --
stdout

$ outanderr 2>&1 | tee file; echo "-- file contents --" && cat file
# redirect both to a file, display both
stdout
stderr
-- file contents --
stdout
stderr

Pertanyaannya adalah: apa yang harus ditulis sebagai ganti tanda tanya untuk mendapatkan hasil di bawah ini:

$ outanderr ???; echo "-- file contents --" && cat file
# redirect both to a file, display stderr
stderr
-- file contents --
stdout
stderr

Kendala:

  • Dengan asumsi bash.
  • Pesanan harus disimpan dalam file.
  • konten stderr ditampilkan dalam garis waktu nyata per baris, yaitu tanpa buffering.
  • File skrip terpisah dapat digunakan.
  • Sihir mungkin diperlukan.

Seberapa besar kendali outanderrprogram yang Anda miliki?
Kevin

1
@ Kevin Saya pikir pertanyaannya lebih umum dari itu. Di sini, outanderrhanya sebuah alias yang mencetak baris ke stdout dan yang lain ke stderr. Idenya (jika memungkinkan) adalah untuk membangun solusi generik yang dapat bekerja dengan program apa pun, tanpa memodifikasi mereka.
lgeorget

@ Lgeorget Saya mengerti itu, tapi saya tidak percaya mungkin untuk benar-benar memenuhi semua kendala dalam solusi generik, jadi saya melihat apakah kita bisa mendapatkan yang spesifik.
Kevin

@ Igeorget benar.
TWiStErRob

Jawaban:


12
2>&1 >>outputfile | tee --append outputfile

Untuk pengujian mudah:

echo -n >outputfile; bash -c "echo stdout >&1; echo stderr >&2" 2>&1 >>outputfile |
  tee --append outputfile; echo "outputfile:"; cat outputfile

Edit 1:

Ini berfungsi dengan menulis stdout (hanya) ke file, membuat sterr stdout sehingga melewati pipa, dan meminta tee menulis hasilnya ke file yang sama.

Kedua penulisan harus dilakukan dalam mode append ( >>bukan >) jika tidak keduanya akan saling menimpa output.

Karena pipa adalah buffer, tidak ada jaminan bahwa output muncul dalam file dalam urutan yang benar. Ini bahkan tidak akan berubah jika aplikasi terhubung ke kedua file deskriptor (dua pipa). Untuk pesanan yang dijamin, kedua output harus melalui saluran yang sama dan ditandai masing-masing. Atau Anda akan membutuhkan beberapa barang yang benar-benar mewah:

  1. Jika stdout dan stderr diarahkan ke suatu file (bukan file yang sama!) Dan kedua file tersebut memiliki volume FUSE maka modul FUSE dapat menandai setiap tulisan dengan stempel waktu sehingga aplikasi kedua dapat mengurutkan data dengan benar dan menggabungkannya. untuk file output nyata. Atau Anda tidak menandai data tetapi minta modul membuat file output gabungan. Kemungkinan besar belum ada modul FUSE yang melakukan ini ...
  2. Baik stdout dan stderr dapat diarahkan ke /dev/null. Output dari aplikasi akan dipisahkan dengan menjalankannya strace -f -s 32000 -e trace=write. Anda harus membalik pelarian dalam kasus itu. Tidak perlu dikatakan bahwa aplikasi tidak berjalan lebih cepat dengan dilacak.
  3. Mungkin hal yang sama dapat dicapai dengan menggunakan modul FUSE yang ada dan sederhana dan menelusuri modul alih-alih aplikasi. Ini mungkin lebih cepat daripada melacak aplikasi karena (atau lebih tepatnya: jika) modul mungkin memiliki syscalls jauh lebih sedikit daripada aplikasi.
  4. Jika aplikasi itu sendiri dapat dimodifikasi: Aplikasi dapat dihentikan setelah setiap output (tapi saya pikir ini hanya mungkin dari dalam) dan terus hanya setelah menerima sinyal (SIGUSR1 atau SIGCONT). Pembacaan aplikasi dari pipa harus memeriksa pipa dan file untuk data baru dan mengirim sinyal setelah setiap data baru. Tergantung pada jenis aplikasi ini mungkin lebih cepat atau bahkan lebih lambat daripada metode strace. FUSE akan menjadi solusi kecepatan maksimum.

1
Bah Tangkap saya di tengah menulis jawaban yang persis sama mengapa tidak.
Kevin

2
NB ini memiliki kondisi perlombaan memperkenalkan kemungkinan bertukar garis / err, tapi saya tidak berpikir itu bisa dihindari.
Kevin

1
@Kevin Itu terjadi pada yang terbaik dari kita, saya sudah menderita sebelumnya dan hampir meminta fitur "tunjukkan bahwa seseorang sedang menulis" (yang akan rumit, meskipun). Sepertinya saya bahwa kondisi lomba hanya terjadi jika penulisan ke file (stdout) terjadi setelah menulis ke pipa.
Hauke ​​Laging

Bukankah itu mengirim kedua stdoutdan stderruntuk tee, atau aku kehilangan sesuatu? Saya pikir persyaratan OP adalah tee stderrhanya.
Joseph R.

@ JosephephR. Anda tidak mencobanya?
Hauke ​​Laging
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.