سؤال bash: طباعة stderr باللون الأحمر


هل هناك طريقة لجعل عرض باش ستدير الرسائل باللون الأحمر؟


99
2017-08-26 21:10


الأصل


أعتقد أن bash لن يلوِّث إنتاجه أبدًا ؛ فقد يرغب بعض البرامج في تحليل شيء ما ، وسيؤدي التلوين إلى إفساد البيانات باستخدام تسلسلات هروب. يجب على تطبيق واجهة المستخدم الرسومية التعامل مع الألوان ، على ما أظن. - kolypto
الجمع بين Balázs Pozsár و killdash9 الجواب يعطي هش: function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') }  يعمل لباش و zsh. لا يمكن إضافة هذا كسمعة جواب b / c. - Heinrich Hartmann
أنا في انتظار إجابة لتعديل bash للقيام بذلك. الحلول دون كل شيء في الواقع تعديل stderr وربما حتى إعادة ترتيبها w.r.t. stdout الذي يكسر الأشياء عندما يجب الحفاظ على تسلسل البايت الدقيق من stderr على سبيل المثال. عندما الأنابيب. - masterxilo


الأجوبة:


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

84
2017-08-26 21:39



عظيم! ولكن أتساءل عما إذا كان هناك طريقة لجعلها دائمة :) - kolypto
نصيحة رائعة! الاقتراح: عن طريق إضافة >&2 قبل ; done)، يتم كتابة الإخراج المقصود stderr في الواقع إلى stderr. هذا مفيد إذا كنت تريد التقاط الإخراج العادي للبرنامج. - henko
الاستخدامات التالية tput، وأكثر قابلية للقراءة قليلاً في رأيي: command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done) - Stefan Lasiewski
أعتقد أن تنفيذ عمليات tput 2 لكل خط الإخراج غير أنيق على الإطلاق. ربما إذا قمت بتخزين إخراج أوامر tput في متغير واستخدامها لكل صدى. ولكن مرة أخرى ، القراءة ليست أفضل. - Balázs Pozsár
هذا الحل لا يحافظ على المسافات البيضاء ولكني أحبها لإيجازها. IFS= read -r line يجب أن تساعد ولكن لا. غير متأكد من السبب. - Max Murphy


الطريقة 1: استخدام عملية استبدال:

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

الطريقة 2: إنشاء دالة في برنامج نصي bash:

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

استخدمه على النحو التالي:

$ color command

كلتا الطريقتين سوف تظهر الأوامر stderr بالأحمر.

استمر في القراءة للحصول على شرح للطريقة التي تعمل بها الطريقة 2. هناك بعض الميزات المثيرة للاهتمام التي أظهرها هذا الأمر.

  • color()... - ينشئ دالة bash تسمى اللون.
  • set -o pipefail - هذا هو الخيار shell الذي يحافظ على رمز إرجاع الخطأ لأمر يتم توجيه الإخراج منه إلى أمر آخر. يتم ذلك في subshell ، والذي يتم إنشاؤه بواسطة الأقواس ، حتى لا تغير خيار pipefail في الغلاف الخارجي.
  • "$@" - ينفذ الحجج إلى وظيفة كأمر جديد. "$@" ما يعادل "$1" "$2" ...
  • 2>&1 - يعيد توجيه stderr من الأمر ل stdout بحيث يصبح sedالصورة stdin.
  • >&3 - اختزال ل 1>&3، هذه عمليات إعادة التوجيه stdout إلى واصف ملف مؤقت جديد 3. 3 يحصل على العودة إلى stdout في وقت لاحق.
  • sed ... - بسبب عمليات إعادة التوجيه أعلاه ، sedالصورة stdin هل stderr من الأمر المنفذة. وتتمثل وظيفته في إحاطة كل سطر برموز الألوان.
  • $'...' بنية باش تؤدي إلى فهم الأحرف التي تم تخطيها بخط مائل عكسي
  • .* - يطابق كامل الخط.
  • \e[31m - تسلسل هروب ANSI الذي يتسبب في جعل الأحرف التالية حمراء
  • & - ال sed استبدال الحرف الذي يتسع إلى سلسلة كاملة متطابقة (السطر بأكمله في هذه الحالة).
  • \e[m - تسلسل هروب ANSI الذي يعيد تعيين اللون.
  • >&2 - اختزال ل 1>&2، هذه عمليات إعادة التوجيه sedالصورة stdout إلى stderr.
  • 3>&1 - يعيد توجيه واصف الملف المؤقت 3 الرجوع الى stdout.

74
2018-04-23 20:53



+1 أفضل إجابة! استبدلت تماما! - muhqu
إجابة رائعة وشرح أفضل - Daniel Serodio
لماذا تحتاج إلى القيام بكل إعادة التوجيه الإضافية؟ يبدو مثل مبالغة - qodeninja
qodeninja يوضح الشرح الغرض من إعادة التوجيه. إذا كنت تستطيع العثور على طريقة أبسط للقيام بذلك ، فأنا أحب أن أرى ذلك! - killdash9
هل هناك طريقة لجعلها تعمل في zsh؟ - Eyal Levin


يمكنك أيضا التحقق من stderred: https://github.com/sickill/stderred


23
2017-12-13 21:40



واو ، هذه الأداة رائعة ، الشيء الوحيد الذي تحتاج إليه هو أن يكون لديك مستودع مناسب يقوم بتثبيته لجميع المستخدمين ، مع سطر واحد ، وليس الاضطرار إلى القيام بمزيد من العمل لتمكينه. - sorin
بدا للعمل بشكل جيد عندما اختبرت مع نص البناء في محطة منفصلة ، ولكن أنا متردد في استخدامه على الصعيد العالمي (في .bashrc). شكرا على كل حال! - Joel Purra
في نظام OS X El Capitan ، تكون الطريقة التي يعمل بها هذا (DYLD_INSERT_LIBRARIES) "مقطوعة" في ثنائيات النظام لأنها محمية بواسطة SIP. لذلك قد يكون من الأفضل استخدام خيارات bash المعطاة في إجابات أخرى. - hmijail
@ hamijail لنظام MacOS يرجى اتباع github.com/sickill/stderred/issues/60 حتى نتمكن من العثور على حل بديل ، جزئي موجود بالفعل ولكن قليلا عربات التي تجرها الدواب. - sorin


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


14
2017-08-26 21:18





طريقة باش لصنع ستدير الأحمر بشكل دائم يستخدم "exec" لإعادة توجيه التدفقات. أضف ما يلي إلى bashrc:

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;'

لقد نشرت على هذا سابقا: كيفية تعيين لون الخط لـ STDOUT و STDERR


11
2018-01-29 08:49



ذات صلة: unix.stackexchange.com/questions/367636/... - Blauhirn
هذا هو أفضل إجابة حتى الآن. من السهل تنفيذها دون تثبيت / تتطلب امتياز sudo ، ويمكن تعميمها على جميع الأوامر. - Luke Davis
للأسف هذا لا يلعب بشكل جيد مع تسلسل الأوامر (الأمر && nextCommand || errorHandlerCommand). يذهب الإخراج الخطأ بعد الإخراج errorHandlerCommand. - carlin.scott
وبالمثل ، إذا كنت source ~/.bashrc مرتين مع هذا ، يتم قفل الجهاز الخاص بي بشكل أساسي. - Dolph
Dolf: في بلدي bashrc أنا بسهولة حماية ضد هذا مع بيان إذا المحيطة بها لمنع هذا الرمز من إعادة التحميل. وإلا ، فستكون المشكلة هي "إعادة exec 9> & 2" بعد حدوث إعادة التوجيه بالفعل. ربما يمكنك تغييره إلى ثابت إذا كنت تعرف مكان> 2 يشير في الأصل. - gospes


لقد قمت بإعداد برنامج ملحمي يقوم بتطبيق إجابة Balázs Pozsár في bash. احفظه في PATH $ وأوامر prefix لتلوين الإخراج الخاص بهم.


    #! / بن / سحق

    إذا كان [$ 1 == "--help"] ؛ ثم
        echo "تنفيذ أمر وتلوين كافة الأخطاء التي حدثت"
        echo "مثال:` basename $ {0} `wget ..."
        صدى "(ج) o_O Tync ، ICQ # 1227-700 ، استمتع!"
        الخروج 0
        فاي

    # ملف مؤقت للقبض على جميع الأخطاء
    TMP_ERRS = $ (mktemp)

    # تنفيذ الأوامر
    "$ @" 2>> (أثناء قراءة السطر ؛ فعل echo -e "\ e [01؛ 31m $ line \ e [0m" | tee --append $ TMP_ERRS؛ done)
    EXIT_CODE = $؟

    # عرض جميع الأخطاء مرة أخرى
    إذا كان [-s "$ TMP_ERRS"]؛ ثم
        echo -e "\ n \ n \ n \ e [01؛ 31m === ERRORS === \ e [0m"
        قطة $ TMP_ERRS
        فاي
    rm -f $ TMP_ERRS

    # إنهاء
    الخروج من EXIT_CODE


7
2017-08-26 22:13



يمكن جعل هذا أكثر كفاءة إذا تم وضع "| tee ..." بعد "done". - Juliano


يمكنك استخدام وظيفة كهذه


 #!/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



لا تعالج المشكلة. لم تقدم طريقة لفصل stderr من stdout ، وهو ما يهم O.P. - Jeremy Visser


لدي نسخة معدلة قليلاً من البرنامج النصي O_o Tync. كنت بحاجة إلى إجراء هذه التعديلات على OS X Lion وهي ليست مثالية لأن البرنامج النصي ينجح أحيانًا قبل أن يتم تنفيذ الأمر الملفوف. لقد أضفت نومًا لكنني متأكد من أن هناك طريقة أفضل.

#!/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