Saya ingin mengatur terminal saya sehingga stderr
dicetak dalam warna yang berbeda dari stdout
; mungkin merah. Ini akan membuatnya lebih mudah untuk membedakan keduanya.
Apakah ada cara untuk mengkonfigurasi ini .bashrc
? Jika tidak, apakah ini mungkin?
Catatan : Pertanyaan ini digabungkan dengan pertanyaan lain yang diminta stderr
, stdout
dan input pengguna bergema menjadi output dalam 3 warna berbeda . Jawaban dapat menjawab salah satu pertanyaan.
Jawaban:
Ini adalah versi yang lebih sulit dari Tampilkan hanya stderr di layar tetapi tulis stdout dan stderr ke file .
Aplikasi yang berjalan di terminal menggunakan saluran tunggal untuk berkomunikasi dengannya; aplikasi memiliki dua port output, stdout dan stderr, tetapi keduanya terhubung ke saluran yang sama.
Anda dapat menghubungkan salah satunya ke saluran yang berbeda, menambah warna ke saluran itu, dan menggabungkan kedua saluran, tetapi ini akan menyebabkan dua masalah:
␛[31m
Berarti “beralih ke latar depan merah”. Ini berarti bahwa jika beberapa output yang ditujukan ke stdout tiba seperti halnya beberapa output untuk stderr ditampilkan, outputnya akan berubah warna. (Lebih buruk lagi, jika ada saklar saluran di tengah urutan pelarian, Anda akan melihat sampah.)Pada prinsipnya, adalah mungkin untuk menulis sebuah program yang mendengarkan pada dua ptys¹, secara serempak (yaitu tidak akan menerima input pada satu saluran saat sedang memproses output pada saluran lain), dan segera mengeluarkan ke terminal dengan instruksi pengubahan warna yang sesuai. Anda kehilangan kemampuan untuk menjalankan program yang berinteraksi dengan terminal. Saya tidak tahu penerapan metode ini.
Pendekatan lain yang mungkin akan menyebabkan program untuk menghasilkan urutan perubahan warna yang tepat, dengan mengaitkan semua fungsi libc yang memanggil
write
system call di perpustakaan yang dimuatLD_PRELOAD
. Lihat jawaban sickill untuk implementasi yang ada, atau jawaban Stéphane Chazelas untuk pendekatan campuran yang memanfaatkanstrace
.Dalam praktiknya, jika itu berlaku, saya sarankan mengarahkan stderr ke stdout dan menyalurkannya ke colorizer berbasis pola seperti colortail atau multitail , atau pewarnaan dengan tujuan khusus seperti colorgcc atau colormake .
¹ terminal palsu. Pipa tidak akan berfungsi karena buffering: sumbernya bisa menulis ke buffer, yang akan merusak sinkronisitas dengan colorizer.
sumber
LD_PRELOAD
trik untuk mencegatwrite
panggilan tampaknya yang paling tepat, IMO (tapi sekali lagi, mungkin ada perbedaan pada rasa * nix tertentu.)write
saja tidak akan berfungsi karena sebagian besar aplikasi tidak memanggil secara langsung, tetapi fungsi lain dari beberapa pustaka bersama (sepertiprintf
) yang akan memanggil yang asliwrite
write
bungkus syscall. Apakah ini diuraikan dalam fungsi-fungsi lain di Glibc?write
viaLD_PRELOAD
seperti yang Anda gambarkan.Lihat
stderred
. MenggunakanLD_PRELOAD
untuk menghubungkan kelibc
'swrite()
panggilan, mewarnai semuastderr
keluaran akan terminal. (Merah secara default.)sumber
Mewarnai input pengguna sulit karena dalam setengah kasus, itu adalah output oleh driver terminal (dengan gema lokal) sehingga dalam kasus itu, tidak ada aplikasi yang berjalan di terminal yang mungkin tahu kapan pengguna akan mengetik teks dan mengubah warna output sesuai . Hanya driver pseudo-terminal (di kernel) yang tahu (emulator terminal (seperti xterm) mengirimkannya beberapa karakter pada beberapa penekanan tombol dan driver terminal dapat mengirim kembali beberapa karakter untuk gema, tetapi xterm tidak dapat mengetahui apakah itu berasal dari gema lokal atau dari apa output aplikasi ke sisi budak dari terminal semu).
Dan kemudian, ada mode lain di mana driver terminal diberitahu untuk tidak menggema, tetapi aplikasi kali ini mengeluarkan sesuatu. Aplikasi (seperti yang menggunakan readline seperti gdb, bash ...) dapat mengirimkannya pada stdout atau stderr yang akan sulit dibedakan dari sesuatu yang di-output untuk hal-hal lain selain menggemakan kembali input pengguna.
Kemudian untuk membedakan stdout aplikasi dari stderr, ada beberapa pendekatan.
Banyak dari mereka melibatkan mengarahkan perintah stdout dan stderr ke pipa dan pipa-pipa itu dibaca oleh aplikasi untuk mewarnainya. Ada dua masalah dengan itu:
Pendekatan lain adalah memodifikasi aplikasi sehingga warna stdout dan stdin. Seringkali tidak mungkin atau realistis untuk dilakukan.
Maka trik (untuk aplikasi yang terhubung secara dinamis) dapat dengan membajak (menggunakan
$LD_PRELOAD
seperti dalam jawaban sickill ) fungsi keluaran yang disebut oleh aplikasi untuk menampilkan sesuatu dan memasukkan kode di dalamnya yang menetapkan warna latar depan berdasarkan apakah mereka dimaksudkan untuk menghasilkan sesuatu pada stderr atau stdout. Namun, itu berarti membajak setiap fungsi yang mungkin dari pustaka C dan pustaka lain yang melakukanwrite(2)
syscall secara langsung dipanggil oleh aplikasi yang berpotensi berakhir menulis sesuatu di stdout atau stderr (printf, put, perror ...), dan bahkan kemudian , yang dapat mengubah perilakunya.Pendekatan lain bisa menggunakan trik PTRACE seperti
strace
ataugdb
lakukan untuk mengaitkan diri kita sendiri setiap kaliwrite(2)
panggilan sistem dipanggil dan mengatur warna output berdasarkan pada apakahwrite(2)
ada pada file deskriptor 1 atau 2.Namun, itu hal yang cukup besar untuk dilakukan.
Trik yang baru saja saya mainkan adalah dengan membajak
strace
dirinya sendiri (yang melakukan pekerjaan kotor dengan mengaitkan dirinya sendiri sebelum setiap panggilan sistem) menggunakan LD_PRELOAD, untuk mengatakannya untuk mengubah warna output berdasarkan apakah ia telah mendeteksiwrite(2)
pada fd 1 atau 2.Dari melihat
strace
kode sumber, kita dapat melihat bahwa semua outputnya dilakukan melaluivfprintf
fungsi. Yang perlu kita lakukan adalah membajak fungsi itu.Pembungkus LD_PRELOAD akan terlihat seperti:
Lalu, kami kompilasi dengan:
Dan gunakan sebagai:
Anda akan melihat bagaimana jika Anda menggantinya
some-cmd
denganbash
, bash prompt dan apa yang Anda ketik muncul dengan warna merah (stderr) sementara denganzsh
itu muncul dalam warna hitam (karena zsh dups stderr ke fd baru untuk menampilkan prompt dan gema).Tampaknya bekerja dengan sangat baik bahkan untuk aplikasi yang tidak Anda harapkan (seperti yang menggunakan warna).
Mode pewarnaan adalah keluaran pada
strace
stderr yang dianggap terminal. Jika aplikasi mengarahkan ulang stdout atau stderr, strace kami yang dibajak akan terus menulis urutan pewarnaan escape pada terminal.Solusi itu memiliki keterbatasan:
strace
: masalah kinerja, Anda tidak dapat menjalankan perintah PTRACE lainnya sepertistrace
ataugdb
di dalamnya, atau masalah setuid / setgidwrite
pada stdout / stderr dari setiap proses individu. Jadi misalnya, insh -c 'echo error >&2'
,error
akan berwarna hijau karenaecho
menampilkannya pada stdout -nya (yang harus diarahkan ke sh's stderr, tetapi semua strace saw adalah awrite(1, "error\n", 6)
). Dan dalamsh -c 'seq 1000000 | wc'
,seq
tidak banyak atauwrite
s untuk yang stdout, sehingga bungkusnya akan berakhir outputing banyak (tak terlihat) melarikan diri urutan ke terminal.sumber
strace $CMD | vim -c ':set syntax=strace' -
.Inilah bukti konsep yang saya lakukan beberapa waktu lalu.
Ini hanya berfungsi di zsh.
Ini juga mengasumsikan Anda memiliki fungsi yang disebut setcolor.
Versi yang disederhanakan:
sumber
exec 2> >(rederr)
. Kedua versi akan memiliki masalah yang saya sebutkan dalam jawaban saya, tentang penataan ulang baris dan mempertaruhkan output hancur (terutama dengan garis panjang).seterr
harus menjadi skrip mandiri, bukan fungsi.Lihat Mike Schiraldi ini Hilite yang melakukan ini untuk satu perintah pada satu waktu. Sapuan saya sendiri melakukan ini untuk seluruh sesi, tetapi juga memiliki banyak fitur / keanehan lain yang mungkin tidak Anda inginkan.
sumber
Beberapa diskusi sebelumnya tentang kesalahan server.
Lihat juga grc dan blog yang membantu tentang hal itu.
sumber