Bagaimana saya bisa menggunakan BASH magic untuk mencapai ini?
Saya hanya ingin melihat output stderr di layar,
tetapi saya ingin stdout dan stderr ditulis ke file.
Klarifikasi: Saya ingin stdout dan stderr berakhir di file yang sama. Dalam urutan itu terjadi.
Sayangnya tidak ada jawaban di bawah ini yang melakukan ini.
bash
shell
io-redirection
Andreas
sumber
sumber
Jawaban:
Bahkan tanpa redirection, atau dengan apa pun kecuali
>logfile 2>&1
, Anda tidak dijamin melihat output dalam urutan generasi.Sebagai permulaan, stdout dari aplikasi akan menjadi buffer-line (to tty) atau buffered (ke pipeline) tetapi stderr tidak terganggu, sehingga hubungan antara urutan output terputus sejauh yang diperhatikan pembaca. Tahap-tahap berikutnya dalam pipa apa pun yang dapat Anda buat tidak akan mendapatkan akses yang terurut secara deterministik ke dua aliran (itu adalah hal-hal yang secara konseptual terjadi secara paralel, dan Anda selalu tunduk pada penjadwal - jika pada saat pembaca Anda mendapat sepotong, penulis sudah memiliki ditulis ke kedua pipa, Anda tidak bisa mengatakan mana yang lebih dulu).
"[T] dia memesan itu terjadi" hanya benar-benar diketahui aplikasi. Urutan output di stdout / stderr adalah masalah yang terkenal - klasik, mungkin -.
sumber
Bila Anda menggunakan konstruksi:
1>stdout.log 2>&1
baik stderr dan stdout mendapatkan diarahkan ke file karena stdout pengalihan diatur sebelum stderr redirection.Jika Anda membatalkan pesanan Anda bisa mendapatkan stdout diarahkan ke file dan kemudian salin stderr ke stdout sehingga Anda dapat mengirimnya
tee
.sumber
tee -a
file yang sama dengan yang digunakan1>
untuk menjumlahkan kedua output dalam file yang sama. Sesuatu seperti:./test 2>&1 1>out+err.log | tee -a out+err.log
wget -O - www.google.de
untuk saya. (bandingkan dengan solusi di bawah ini)tee -a
tidak akan bekerja andal untuk memiliki output yang sama dengan yang ada di konsol jika tidak ada yang dialihkan. Output yang masuktee
mungkin sedikit tertunda dibandingkan dengan output yang datang langsung dari perintah, dan mungkin muncul nanti di log.Saya dapat mencapai ini dengan menempatkan baris berikut di bagian atas skrip bash:
Ini akan mengarahkan stdout ke file
log
(1>>log
), lalu tee stderr ke filelog
(2> >(tee -a log
) dan mengarahkannya kembali ke stderr (>&2)
. Dengan cara ini, saya mendapatkan satu filelog
,, yang menunjukkan urutan stdout dan stderr secara berurutan, dan stderr juga ditampilkan di layar seperti biasa.Tangkapannya adalah bahwa itu hanya berfungsi ketika saya menambahkan file. Jika saya tidak menambahkan, tampaknya kedua pengalihan saling berkeping-keping, dan saya hanya mendapatkan satu keluaran terakhir.
sumber
Anda ingin menduplikasi aliran kesalahan sehingga muncul di konsol dan di file log. Alat untuk itu adalah
tee
, dan yang perlu Anda lakukan adalah menerapkannya ke aliran kesalahan. Sayangnya, tidak ada shell konstruksi standar untuk menyalurkan aliran kesalahan perintah ke perintah lain, sehingga diperlukan sedikit penataan ulang deskriptor file.sumber
tee
memperkenalkan penundaan di sini juga. Saya tidak berpikir ada solusi shell murni. Sebenarnya saya bertanya-tanya apakah ada solusi tanpa memodifikasi aplikasi dengan cara tertentu.Untuk menulis stderr ke layar dan menulis KEDUA stderr dan stdout ke file - DAN memiliki baris untuk stderr dan stdout keluar dalam urutan yang sama seperti jika keduanya ditulis ke layar:
Ternyata menjadi masalah yang sulit, terutama bagian tentang memiliki "urutan yang sama" yang Anda harapkan jika Anda hanya menulisnya di layar. Secara sederhana: Tulis masing-masing ke file sendiri, lakukan beberapa sihir proses latar belakang untuk menandai setiap baris (dalam setiap file) dengan waktu yang tepat garis itu diproduksi, dan kemudian: "ekor - ikuti" file stderr ke layar , tetapi untuk melihat KEDUA "stderr" dan "stdout" bersama - secara berurutan - urutkan kedua file (dengan tanda waktu yang tepat pada setiap baris) bersamaan.
Kode:
Ya, ini tampaknya rumit, dan menghasilkan 4 file output (2 di antaranya dapat Anda hapus). Tampaknya ini adalah masalah yang sulit untuk dipecahkan, jadi butuh beberapa mekanisme.
Pada akhirnya, untuk melihat hasil dari KEDUA stdout dan stderr dalam urutan yang Anda harapkan, jalankan ini:
Satu-satunya alasan urutannya setidaknya sangat dekat dengan apa yang seharusnya dimiliki stdout dan stderr hanya pergi ke layar adalah: Setiap baris ditandai dengan cap waktu hingga milidetik.
Untuk melihat stderr di layar saat proses berjalan, gunakan ini:
Harapan yang membantu seseorang keluar, yang tiba di sini lama setelah pertanyaan awal diajukan.
sumber
Biarkan
f
menjadi perintah yang Anda ingin dieksekusi, maka iniharus memberi Anda apa yang Anda inginkan. Sebagai contoh
wget -O - www.google.de
akan terlihat seperti ini:sumber
Mengingat apa yang saya baca di sini, satu-satunya solusi yang dapat saya lihat adalah dengan menambahkan setiap baris apakah STOUT atau STERR dengan timeslice / timestamp. date +% s akan menjadi detik, tapi itu lambat untuk mempertahankan pesanan. Log juga harus disortir. Lebih banyak pekerjaan daripada yang saya mampu.
sumber
Saya telah berjuang dengan persyaratan yang tepat ini, dan pada akhirnya tidak dapat menemukan solusi sederhana. Apa yang akhirnya saya lakukan adalah ini:
Ini menambahkan stdout dan stderr, dalam urutan disisipkan tepat, ke file log. Dan jika ada kesalahan terjadi (sebagaimana ditentukan oleh status keluar dari perintah), ia mengirimkan seluruh output (stdout dan stderr) ke stdout, lagi-lagi dalam urutan disisipkan yang tepat. Saya menemukan ini sebagai kompromi yang masuk akal untuk kebutuhan saya. Jika Anda menginginkan file log sekali pakai daripada yang sedang tumbuh banyak file, itu bahkan lebih sederhana:
sumber
stderr ke perintah-diganti
tee -a
, dan stdout menambahkan ke file yang sama:dan perhatikan: pastikan juga urutan yang benar (tetapi tanpa stderr-show) ada perintah 'unbuffer' dari alat 'expect', yang mensimulasikan tty dan menjaga stdout / err tetap seperti yang akan ditampilkan di terminal:
sumber