Pertanyaan bash: cetak stderr dalam warna merah


Apakah ada cara untuk membuat tampilan bash stderr pesan dalam warna merah?


97
2017-08-26 21:10




Saya kira bash tidak akan pernah mewarnai outputnya: beberapa program mungkin ingin mem-parsing sesuatu, dan pewarnaan akan merusak data dengan urutan melarikan diri. Aplikasi GUI harus menangani warna, saya kira. - kolypto
Menggabungkan jawaban Balázs Pozsár dan killdash9 memberi renyah: function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') }  Bekerja untuk bash dan zsh. Tidak dapat menambahkan ini sebagai jawaban b / c reputasi. - Heinrich Hartmann
Saya menunggu jawaban yang memodifikasi bash untuk melakukan ini. Solusi di bawah ini semua sebenarnya memodifikasi stderr dan bahkan mungkin menyusunnya w.r.t. stdout yang memecahkan hal-hal ketika urutan byte stderr yang tepat harus dipertahankan misalnya, saat piping. - masterxilo


Jawaban:


command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)

84
2017-08-26 21:39



Besar! Tapi saya ingin tahu apakah ada cara untuk membuatnya permanen :) - kolypto
Kiat hebat! Saran: Dengan menambahkan >&2 tepat sebelum ; done), output yang ditujukan untuk stderr sebenarnya ditulis ke stderr. Itu membantu jika Anda ingin menangkap output normal dari program. - henko
Penggunaan berikut tput, dan sedikit lebih mudah dibaca menurut saya: command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done) - Stefan Lasiewski
Saya pikir mengeksekusi 2 proses tput untuk setiap jalur output tidak elegan sama sekali. Mungkin jika Anda akan menyimpan output dari perintah tput dalam variabel dan menggunakannya untuk setiap gema. Tetapi sekali lagi, keterbacaan tidak benar-benar lebih baik. - Balázs Pozsár
Solusi ini tidak melestarikan spasi tetapi saya menyukainya karena singkatnya. IFS= read -r line harus membantu tetapi tidak. Tidak yakin kenapa. - Max Murphy


Metode 1: Gunakan substitusi proses:

command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)

Metode 2: Buat fungsi dalam skrip bash:

color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1

Gunakan seperti ini:

$ color command

Kedua metode akan menampilkan perintah stderr merah.

Teruslah membaca untuk penjelasan tentang cara kerja metode 2. Ada beberapa fitur menarik yang ditunjukkan oleh perintah ini.

  • color()... - Menciptakan fungsi bash yang disebut warna.
  • set -o pipefail - Ini adalah opsi shell yang menyimpan kode kembali kesalahan dari perintah yang outputnya disalurkan ke perintah lain. Ini dilakukan dalam subkulit, yang dibuat oleh tanda kurung, agar tidak mengubah opsi pipefail di kulit terluar.
  • "$@" - Eksekusi argumen ke fungsi sebagai perintah baru. "$@" setara dengan "$1" "$2" ...
  • 2>&1 - Arahkan ulang stderr dari perintah untuk stdout jadi itu menjadi sed's stdin.
  • >&3 - Singkatan untuk 1>&3, pengalihan ini stdout ke deskriptor file sementara baru 3. 3 akan diarahkan kembali stdout kemudian.
  • sed ... - Karena pengalihan di atas, sed's stdin adalah stderr dari perintah yang dieksekusi. Fungsinya mengelilingi setiap baris dengan kode warna.
  • $'...' Konstruksi bash yang menyebabkannya untuk memahami karakter backslash-escape
  • .* - Mencocokkan seluruh garis.
  • \e[31m - Urutan pelolosan ANSI yang menyebabkan karakter berikut menjadi merah
  • & - The sed ganti karakter yang diperluas ke seluruh string yang cocok (seluruh baris dalam kasus ini).
  • \e[m - Urutan pelolosan ANSI yang menyetel ulang warna.
  • >&2 - Singkatan untuk 1>&2, pengalihan ini sed's stdout untuk stderr.
  • 3>&1 - Redirect file deskriptor sementara 3 kembali ke stdout.

72
2018-04-23 20:53



+1 jawaban terbaik! absolutly diremehkan! - muhqu
Jawaban yang bagus dan penjelasan yang lebih baik - Daniel Serodio
Mengapa Anda perlu melakukan semua pengalihan tambahan? tampak seperti berlebihan - qodeninja
@qodeninja Penjelasan memberikan tujuan untuk redirection. Jika Anda dapat menemukan cara yang lebih mudah untuk melakukannya, saya ingin melihatnya! - killdash9
Apakah ada cara untuk membuatnya bekerja zsh? - Eyal Levin


Anda juga dapat memeriksa stderred: https://github.com/sickill/stderred


23
2017-12-13 21:40



Wow, utilitas ini hebat, satu-satunya hal yang perlu adalah memiliki repositori yang tepat yang menginstalnya untuk semua pengguna, dengan satu baris, tidak harus melakukan lebih banyak pekerjaan untuk mengaktifkannya. - sorin
Tampak berfungsi dengan baik ketika saya mengujinya dengan skrip build di terminal terpisah, tapi saya ragu untuk menggunakannya secara global (di .bashrc). Terimakasih Meskipun! - Joel Purra
Di OS X El Capitan, cara kerjanya (DYLD_INSERT_LIBRARIES) "rusak" dalam binari sistem karena dilindungi oleh SIP. Jadi mungkin lebih baik menggunakan opsi bash yang diberikan dalam jawaban lain. - hmijail
@hmijail untuk MacOS silakan ikuti github.com/sickill/stderred/issues/60 sehingga kita dapat menemukan solusi, yang sebagian sudah ada tetapi sedikit buggy. - sorin


http://sourceforge.net/projects/hilite/


14
2017-08-26 21:18





Cara bash pembuatan stderr secara permanen merah menggunakan 'exec' untuk mengarahkan aliran. Tambahkan yang berikut ke bashrc Anda:

exec 9>&2
exec 8> >(
    while IFS='' read -r line || [ -n "$line" ]; do
       echo -e "\033[31m${line}\033[0m"
    done
)
function undirect(){ exec 2>&9; }
function redirect(){ exec 2>&8; }
trap "redirect;" DEBUG
PROMPT_COMMAND='undirect;'

Saya telah memposting ini sebelumnya: Cara mengatur warna font untuk STDOUT dan STDERR


11
2018-01-29 08:49



terkait: unix.stackexchange.com/questions/367636/… - Blauhirn
Ini adalah jawaban terbaik sejauh ini; mudah diimplementasikan tanpa instalasi / membutuhkan hak istimewa sudo, dan dapat digeneralisasikan ke semua perintah. - Luke Davis
Sayangnya ini tidak bermain dengan baik dengan perintah chaining (command && nextCommand || errorHandlerCommand). Output kesalahan berjalan setelah output errorHandlerCommand. - carlin.scott
Demikian pula, jika saya source ~/.bashrc dua kali dengan ini, terminal saya pada dasarnya terkunci. - Dolph
@ Dolf: Di bashrc saya, saya dengan mudah berjaga-jaga terhadap hal ini dengan pernyataan di sekitarnya jika untuk mencegah pemuatan ulang kode ini. Jika tidak, masalahnya adalah pengalihan 'exec 9> & 2' setelah pengalihan telah terjadi. Mungkin mengubahnya menjadi konstan jika Anda tahu di mana> 2 menunjuk pada awalnya. - gospes


Saya telah membuat skrip pembungkus yang mengimplementasikan jawaban Balázs Pozsár dalam bash murni. Simpan di perintah $ PATH dan awalan Anda untuk mewarnai hasilnya.


    #! / bin / bash

    jika [$ 1 == "--help"]; kemudian
        echo "Menjalankan perintah dan mewarnai semua kesalahan yang terjadi"
        echo "Contoh:` basename $ {0} `wget ..."
        echo "(c) o_O Tync, ICQ # 1227-700, Selamat menikmati!"
        keluar 0
        fi

    # Temp file untuk menangkap semua kesalahan
    TMP_ERRS = $ (mktemp)

    # Jalankan perintah
    "$ @" 2>> (sambil membaca baris; lakukan echo -e "\ e [01; 31m $ line \ e [0m" | tee - tampilkan $ TMP_ERRS; selesai)
    EXIT_CODE = $?

    # Tampilkan semua kesalahan lagi
    jika [-s] $ TMP_ERRS "]; kemudian
        echo -e "\ n \ n \ n \ e [01; 31m === ERRORS === \ e [0m"
        kucing $ TMP_ERRS
        fi
    rm -f $ TMP_ERRS

    # Selesai
    keluar $ EXIT_CODE


7
2017-08-26 22:13



Ini bisa dibuat lebih efisien jika "| tee ..." dimasukkan setelah "selesai". - Juliano


Anda dapat menggunakan fungsi seperti ini


 #!/bin/sh

color() {
      printf '\033[%sm%s\033[m\n' "$@"
      # usage color "31;5" "string"
      # 0 default
      # 5 blink, 1 strong, 4 underlined
      # fg: 31 red,  32 green, 33 yellow, 34 blue, 35 purple, 36 cyan, 37 white
      # bg: 40 black, 41 red, 44 blue, 45 purple
      }
string="Hello world!"
color '31;1' "$string" >&2


3
2017-08-26 22:29



Tidak mengatasi masalah. Anda belum menyediakan cara untuk memisahkan stderr dari stdout, yang mana yang diinginkan O.P. - Jeremy Visser


Saya memiliki versi skrip O_o Tync yang sedikit dimodifikasi. Saya perlu membuat mod ini untuk OS X Lion dan itu tidak sempurna karena skrip kadang-kadang selesai sebelum perintah yang dibungkus. Saya telah menambahkan tidur tapi saya yakin ada cara yang lebih baik.

#!/bin/bash

   if [ $1 == "--help" ] ; then
       echo "Executes a command and colorizes all errors occured"
       echo "Example: `basename ${0}` wget ..."
       echo "(c) o_O Tync, ICQ# 1227-700, Enjoy!"
       exit 0
       fi

   # Temp file to catch all errors
   TMP_ERRS=`mktemp /tmp/temperr.XXXXXX` || exit 1

   # Execute command
   "$@" 2> >(while read line; do echo -e "$(tput setaf 1)$line\n" | tee -a $TMP_ERRS; done)
   EXIT_CODE=$?

   sleep 1
   # Display all errors again
   if [ -s "$TMP_ERRS" ] ; then
       echo -e "\n\n\n$(tput setaf 1) === ERRORS === "
       cat $TMP_ERRS
   else
       echo "No errors collected in $TMP_ERRS"
   fi
   rm -f $TMP_ERRS

   # Finish
   exit $EXIT_CODE

1
2018-06-08 17:37





Solusi ini berhasil untuk saya: https://superuser.com/questions/28869/immediately-tell-which-output-was-sent-to-stderr

Saya telah menempatkan fungsi ini di komputer saya .bashrc atau .zshrc:

# Red STDERR
# rse <command string>
function rse()
{
    # We need to wrap each phrase of the command in quotes to preserve arguments that contain whitespace
    # Execute the command, swap STDOUT and STDERR, colour STDOUT, swap back
    ((eval $(for phrase in "$@"; do echo -n "'$phrase' "; done)) 3>&1 1>&2 2>&3 | sed -e "s/^\(.*\)$/$(echo -en \\033)[31;1m\1$(echo -en \\033)[0m/") 3>&1 1>&2 2>&3
}

Kemudian misalnya:

$ rse cat non_existing_file.txt

akan memberi saya output merah.


1
2017-08-25 09:16