আমি কী আমার শেলটি বিভিন্ন রঙে STDERR এবং STDOUT মুদ্রণ করতে কনফিগার করতে পারি?


62

আমি আমার টার্মিনালটি সেট আপ করতে চাই তাই stderrআলাদা রঙে মুদ্রিত হয় stdout; হতে পারে লাল। এটি দু'টিকে আলাদা করে বলা সহজ করে তুলবে।

এটিকে কনফিগার করার কোনও উপায় আছে কি .bashrc? যদি তা না হয় তবে কি এটিও সম্ভব?


উল্লেখ্য : এই প্রশ্নের সঙ্গে একীভূত হয়ে যায় অন্য যে জন্য জিজ্ঞাসা stderr, stdout এবং ব্যবহারকারীর ইনপুট echo মধ্যে আউটপুট হতে 3 বিভিন্ন রং । উত্তরগুলি যে কোনও প্রশ্নে সম্বোধন করা হতে পারে।


1
স্ট্যাক ওভারফ্লোতে একই প্রশ্ন: স্ট্যাকওভারফ্লো.com
স্টাফেন গিমেনেজ

আকর্ষণীয় প্রশ্ন + উত্তরগুলি, তবে
লালটি

উত্তর:


32

এটি স্ক্রিনে কেবল স্ট্ডারারের শোয়ের একটি শক্ত সংস্করণ তবে ফাইলে stdout এবং stderr উভয়ই লিখুন

টার্মিনালে চলমান অ্যাপ্লিকেশনগুলি এর সাথে যোগাযোগের জন্য একটি একক চ্যানেল ব্যবহার করে; অ্যাপ্লিকেশনগুলির দুটি আউটপুট পোর্ট রয়েছে, স্টডআউট এবং স্টডার, তবে তারা উভয়ই একই চ্যানেলে সংযুক্ত।

আপনি তাদের মধ্যে একটিকে আলাদা চ্যানেলে সংযুক্ত করতে পারেন, সেই চ্যানেলে রঙ যুক্ত করতে পারেন এবং দুটি চ্যানেলকে একত্রিত করতে পারেন, তবে এটি দুটি সমস্যা সৃষ্টি করবে:

  • মার্জ করা আউটপুট ঠিক একই ক্রমে নাও হতে পারে যেন কোনও পুনঃনির্দেশ ছিল না। এর কারণ হল চ্যানেলের যে কোনও একটিতে যুক্ত হওয়া প্রক্রিয়াকরণটি (কিছুটা) সময় নেয়, তাই রঙিন চ্যানেলটি বিলম্ব হতে পারে। যদি কোনও বাফারিং হয় তবে ব্যাধি আরও খারাপ হবে।
  • টার্মিনালগুলি প্রদর্শনের রঙ নির্ধারণ করতে রঙ পরিবর্তন করে পালানোর ক্রম ব্যবহার করে, উদাহরণস্বরূপ ␛[31m"লাল অগ্রভাগে স্যুইচ করুন" means এর অর্থ এটি যদি স্টডআউট দ্বারা নির্ধারিত কিছু আউটপুট স্টার্ডারের জন্য কিছু আউটপুট প্রদর্শিত হয়, তবে আউটপুটটি বিযুক্ত হবে। (আরও খারাপ, যদি একটি পালানোর ক্রমের মাঝে কোনও চ্যানেল স্যুইচ থাকে তবে আপনি আবর্জনা দেখতে পাবেন))

নীতিগতভাবে, এমন একটি প্রোগ্রাম লিখতে সম্ভব হবে যা দুটি পাইটিসে শুনবে, একযোগে (যেমন অন্য চ্যানেলে আউটপুট প্রসেস করার সময় একটি চ্যানেলে ইনপুট গ্রহণ করবে না) এবং তত্ক্ষণাত উপযুক্ত রঙ পরিবর্তন করার নির্দেশাবলী সহ টার্মিনালে আউটপুট দেয়। আপনি এমন প্রোগ্রামগুলি চালনার দক্ষতা হারাবেন যা টার্মিনালের সাথে ইন্টারঅ্যাক্ট করে। আমি এই পদ্ধতির কোনও প্রয়োগ সম্পর্কে জানি না।

আরেকটি সম্ভাব্য পন্থাটি হ'ল writeএকটি লাইব্রেরিতে সিস্টেম কলকে কল করে এমন সমস্ত libc ফাংশন ঘুরিয়ে সঠিক রঙ পরিবর্তন করার ক্রমগুলি আউটপুট করার জন্য প্রোগ্রামটি সৃষ্টি করা হবে LD_PRELOAD। দেখুন sickill এর উত্তর একটি বিদ্যমান বাস্তবায়নের অথবা Stéphane Chazelas এর উত্তর একটি মিশ্র পদ্ধতির যে লিভারেজ জন্য strace

বাস্তবে, যে যদি প্রযোজ্য হয়, আমি stdout- এ এবং বংশীধ্বনিতুল্য করার দ্বারা stderr একটি প্যাটার্ন-ভিত্তিক colorizer যেমন মধ্যে পুনঃনির্দেশিত করার পরামর্শ দিই colortail বা multitail , অথবা যেমন বিশেষ উদ্দেশ্য colorizers colorgcc বা colormake

Se সিউডো-টার্মিনালগুলি। বাফারিংয়ের কারণে পাইপগুলি কাজ করবে না: উত্সটি বাফারে লিখতে পারে, যা কালারাইজারের সাথে সিঙ্ক্রোনসিটিটি ভেঙে দেয়।


1
স্ট্যাডার স্ট্রিমটি কৌলাইজ করার জন্য কোনও টার্মিনাল প্রোগ্রামটি প্যাচ করা কঠিন হতে পারে না। উবুন্টু মস্তিষ্কে কেউ এরকম কিছু পরামর্শ দিয়েছেন ।
2'11

@ চিহ্নযুক্ত: এর জন্য প্রতিটি টার্মিনাল এমুলেটরের সাথে আপনি কাজ করতে চান এমন পথ প্রয়োজন। কলকে LD_PRELOADবিরত রাখতে ট্রিক ব্যবহার writeকরা সর্বাধিক উপযুক্ত বলে মনে হয়, আইএমও (তবে তারপরে আবার কিছু নির্দিষ্ট * নিক্স স্বাদেও পার্থক্য থাকতে পারে))
অ্যালেক্স

কমপক্ষে লিনাক্সে, writeএকা বাধা দেওয়া কার্যকরভাবে কাজ করবে না কারণ বেশিরভাগ অ্যাপ্লিকেশন সরাসরি কল করে না, তবে কিছু ভাগ করা লাইব্রেরি (যেমন printf) এর অন্য একটি ফাংশন যা write
মূলটিকে

@StephaneChazelas আমি কাছাকাছি hooking চিন্তা ছিল writeপ্রাপ্ত syscall মোড়কের। এটি কি গ্লিবসি-র অন্যান্য কার্যক্রমে অন্তর্ভুক্ত?
গিলস

1
Stderred প্রকল্পের hooking এর একটি বাস্তবায়ন হবে বলে মনে হয় writeমাধ্যমে LD_PRELOADহিসাবে আপনি বর্ণনা করে।
ড্রয় নোকস

36

চেক আউট stderred। এটি ব্যবহার করে LD_PRELOADকরতে হুক libcএর write()কল, সব colorizing stderrআউটপুট একটি টার্মিনালে যাচ্ছে। (ডিফল্ট হিসাবে লাল।)


8
চমৎকার, যে লাইব্রেরি দুর্দান্ত । আসল প্রশ্নটি হল: আমার অপারেটিং সিস্টেম / টার্মিনালটি কেন এই প্রিনস্টল দিয়ে আসে? ;)
নাফটুলি কে

5
আমি ধরে নিলাম আপনি লেখক, এটা কি ঠিক? সেক্ষেত্রে আপনার অনুমোদিততা প্রকাশ করা উচিত।
দিমিত্রি গ্রিগরিয়েভ

15

ব্যবহারকারীর ইনপুট রঙ করা কঠিন কারণ অর্ধেক ক্ষেত্রে এটি টার্মিনাল ড্রাইভারের দ্বারা আউটপুট হয় (স্থানীয় প্রতিধ্বনি সহ) সুতরাং সেক্ষেত্রে সেই টার্মিনালে চলমান কোনও অ্যাপ্লিকেশন জানতে পারে না যে ব্যবহারকারী কখন পাঠ্য টাইপ করতে চলেছে এবং সেই অনুযায়ী আউটপুট রঙ পরিবর্তন করবে । কেবলমাত্র সিউডো-টার্মিনাল ড্রাইভার (কার্নেলের মধ্যে) জানেন (টার্মিনাল এমুলেটর (এক্সটারেমের মতো)) কিছু কিপ্রেসের উপর এটি কিছু অক্ষর প্রেরণ করে এবং টার্মিনাল ড্রাইভারটি প্রতিধ্বনির জন্য কিছু অক্ষর ফেরত পাঠাতে পারে, তবে এক্সটার্ম জানতে পারে না যে সেগুলি থেকে রয়েছে কিনা স্থানীয় প্রতিধ্বনি বা ছদ্ম টার্মিনালের স্লেভ দিকে অ্যাপ্লিকেশন আউটপুট যা থেকে)।

এবং তারপরে, অন্য মোডে আছে যেখানে টার্মিনাল ড্রাইভারকে প্রতিধ্বনি করতে বলা হয়নি, তবে অ্যাপ্লিকেশনটি এবার কিছু আউটপুট করে। অ্যাপ্লিকেশনটি (জিডিবি, বাশ এর মতো রিডলাইন ব্যবহারকারীদের মতো ...) এটি স্টাডাউট বা স্টার্ডারে প্রেরণ করতে পারে যা ব্যবহারকারীর ইনপুট প্রতিধ্বনি ব্যতীত অন্য জিনিসগুলির জন্য এটি আউটপুট করে এমন কিছু থেকে পৃথক করা কঠিন হতে চলেছে।

তারপরে কোনও অ্যাপ্লিকেশনটির স্টাডাউটকে তার স্ট্যাডার থেকে আলাদা করার জন্য বিভিন্ন পন্থা রয়েছে।

তাদের মধ্যে অনেকগুলি স্ট্যান্ডআউট এবং স্ট্ডারকে পাইপগুলিতে পুনর্নির্দেশ করতে জড়িত এবং সেগুলি রঙ করার জন্য কোনও অ্যাপ্লিকেশন দ্বারা পড়া পাইপগুলিকে পাঠায়। এটির সাথে দুটি সমস্যা রয়েছে:

  • Stdout একবার টার্মিনাল না হয়ে (পরিবর্তে পাইপের মতো), অনেক অ্যাপ্লিকেশন তাদের আউটপুট বাফারিং শুরু করার জন্য তাদের আচরণটি খাপ খায় যার অর্থ আউটপুট বড় অংশে প্রদর্শিত হতে চলেছে।
  • এমনকি যদি এটি একই পাইপ দুটি পাইপকে প্রসেস করে তবে স্টাডাউট এবং স্ট্ডার প্রয়োগের দ্বারা লিখিত পাঠ্য ক্রমটি সংরক্ষণ করা হবে না এর কোনও গ্যারান্টি নেই, কারণ পড়ার প্রক্রিয়াটি জানতে পারে না (যদি উভয় থেকে কিছু পড়ার দরকার থাকে) "স্টাডাউট" পাইপ বা "স্ট্ডার" পাইপ থেকে পড়া শুরু করা যায় কিনা।

আর একটি পদ্ধতি হ'ল অ্যাপ্লিকেশনটি সংশোধন করা যাতে এটি এর স্টাডআউট এবং স্টিডিনকে রঙ করে। এটি প্রায়শই সম্ভব বা বাস্তববাদী হয় না।

তারপরে একটি কৌশল (গতিশীলভাবে সংযুক্ত অ্যাপ্লিকেশনগুলির জন্য) হাইজ্যাক ( আধিপত্যের উত্তর$LD_PRELOAD হিসাবে ব্যবহার করে ) আউটপুট ক্রিয়াকলাপকে কিছু আউটপুট আবেদনের জন্য আউটপুট ক্রিয়াকলাপ বলে এবং সেগুলিতে কোড অন্তর্ভুক্ত করা যেতে পারে যা তারা কিছু আউটপুট বোঝাতে চাইছে তার ভিত্তিতে অগ্রভাগের রঙ নির্ধারণ করে stderr বা stdout এ। যাইহোক, এর অর্থ সি লাইব্রেরি এবং অন্য যে কোনও লাইব্রেরি write(2)থেকে অ্যাপ্লিকেশন দ্বারা সরাসরি কল করা একটি সিস্কল করে এমন সম্ভাব্য ক্রিয়াকলাপ হাইজ্যাক করা যা সম্ভবত স্টডআউট বা স্ট্ডার (প্রিন্টফ, পুটস, বিভীষিকাময় ...) লিখতে পারে এবং তারপরেও , এটি এর আচরণ পরিবর্তন করতে পারে।

আরেকটি পদ্ধতি হ'ল পিটিআরসি ট্রিকসটি ব্যবহার করা straceবা নিজেরকে gdbহুক করতে প্রতিবার যখন write(2)সিস্টেম কল বলা হয় এবং write(2)ফাইল বর্ণনাকারী 1 বা 2 তে রয়েছে তার উপর ভিত্তি করে আউটপুট রঙ সেট করে ।

তবে এটি করা বেশ বড় বিষয়।

একটি কৌশল যা আমি সবে খেলছি তা হ'ল হাইজ্যাক straceকরা (যা প্রতিটি সিস্টেম কলের আগে নিজেকে হুক করার নোংরা কাজ করে) এলডিপ্রেলএড ব্যবহার করে, এটি write(2)এফডি 1 বা এটিতে সনাক্ত করেছে কিনা তার ভিত্তিতে আউটপুট রঙ পরিবর্তন করতে বলে 2।

straceউত্স কোডটি দেখার থেকে আমরা দেখতে পাচ্ছি যে এটির আউটপুটগুলি vfprintfফাংশনটির মাধ্যমে সম্পন্ন হয়েছে । আমাদের যা করতে হবে তা হ'ল সেই ফাংশনটি হাইজ্যাক করা।

LD_PRELOAD র‍্যাপারটি দেখতে পাবেন:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>

int vfprintf(FILE *outf, const char *fmt, va_list ap)
{
  static int (*orig_vfprintf) (FILE*, const char *, va_list) = 0;
  static int c = 0;
  va_list ap_orig;
  va_copy(ap_orig, ap);
  if (!orig_vfprintf) {
    orig_vfprintf = (int (*) (FILE*, const char *, va_list))
      dlsym (RTLD_NEXT, "vfprintf");
  }

  if (strcmp(fmt, "%ld, ") == 0) {
    int fd = va_arg(ap, long);
    switch (fd) {
    case 2:
      write(2, "\e[31m", 5);
      c = 1;
      break;
    case 1:
      write(2, "\e[32m", 5);
      c = 1;
      break;
    }
  } else if (strcmp(fmt, ") ") == 0) {
    if (c) write(2, "\e[m", 3);
    c = 0;
  }
  return orig_vfprintf(outf, fmt, ap_orig);
}

তারপরে, আমরা এটি দিয়ে সংকলন করি:

cc -Wall -fpic -shared -o wrap.so wrap.c -ldl

এবং এটি হিসাবে ব্যবহার করুন:

LD_PRELOAD=/path/to/wrap.so strace -qfo /dev/null -e write -s 0 env -u LD_PRELOAD some-cmd

আপনি কিভাবে আপনি প্রতিস্থাপন যদি বিজ্ঞপ্তি পাবেন some-cmdসঙ্গে bash, ব্যাশ প্রম্পট এবং কি আপনি টাইপ লাল (দ্বারা stderr) প্রদর্শিত যখন সঙ্গে zshএটা কালো দেখা (কারণ zsh dups একটি নতুন FD সম্মুখের stderr তার প্রম্পট প্রদর্শন করে এবং echo)।

এমনকি আপনি যে অ্যাপ্লিকেশনগুলি প্রত্যাশা করবেন না তাদের জন্যও এটি আশ্চর্যজনকভাবে ভাল কাজ করেছে বলে মনে হয় (রঙগুলি ব্যবহার করে এমনগুলি পছন্দ করে)।

কালারিং মোডটি straceস্টার্ডারের আউটপুট যা টার্মিনাল হিসাবে ধরে নেওয়া হয়। যদি অ্যাপ্লিকেশনটি তার স্টডআউট বা স্টডার পুনঃনির্দেশ করে, তবে আমাদের হাইজ্যাকড স্ট্রেস টার্মিনালে রঙিন পালানোর ক্রমগুলি লিখতে থাকবে।

এই সমাধানটির সীমাবদ্ধতা রয়েছে:

  • অন্তর্নিহিত strace: পারফরম্যান্সের সমস্যাগুলি, আপনি অন্যান্য পিটিআরসিই কমান্ডগুলি এর মতো straceবা এতে চালাতে পারবেন না gdb, বা সেটআপড / সেটগিড সমস্যাগুলি
  • এটি writeপ্রতিটি স্বতন্ত্র প্রক্রিয়ার স্টাডাউট / স্টডারর উপর ভিত্তি করে রঙ করছে । সুতরাং উদাহরণস্বরূপ, মধ্যে sh -c 'echo error >&2', errorসবুজ হবে কারণ echoএটি তার স্টাডাউটে আউটপুট দেয় (যা sh এর স্ট্যাডারকে পুনঃনির্দেশিত করা হয়েছে, তবে সমস্ত স্ট্রেস দেখায় একটি write(1, "error\n", 6))। আর এ sh -c 'seq 1000000 | wc', seqঅনেক বা না writeকরার গুলি তার তাই মোড়কের (অদৃশ্য) টার্মিনালে সিকোয়েন্স অব্যাহতি অনেকটা outputing শেষ হবে, stdout- এ।

খুশী হলাম। সদৃশ প্রশ্নের উপরে প্রিফিক্সিং র‌্যাপারের পরামর্শ ছিল । আমি প্রশ্নটি মার্জ করার জন্য পতাকাঙ্কিত করেছি যাতে আপনার উত্তরটি সেখানে দেখা যায়।
গিলস

আপনি কি ভিঙ্ক সিনট্যাক্স হাইলাইট টুইট করছেন? strace $CMD | vim -c ':set syntax=strace' -
পাবলো এ

4

আমি ধারণার একটি প্রমাণ এখানে কিছুক্ষণ আগে করেছি।

এটি কেবল zsh এ কাজ করে।

# make standard error red
rederr()
{
    while read -r line
    do
        setcolor $errorcolor
        echo "$line"
        setcolor normal
    done
}

errorcolor=red

errfifo=${TMPDIR:-/tmp}/errfifo.$$
mkfifo $errfifo
# to silence the line telling us what job number the background job is
exec 2>/dev/null
rederr <$errfifo&
errpid=$!
disown %+
exec 2>$errfifo

এটি ধরে নিয়েছে যে আপনার একটি সেট রয়েছে কলক নামক ফাংশন।

সরলীকৃত সংস্করণ:

setcolor()
{
    case "$1" in
    red)
        tput setaf 1
        ;;
    normal)
        tput sgr0
        ;;
    esac
}

এই কাজ করার জন্য একটি অনেক সহজ উপায় আছে: exec 2> >(rederr)। উভয় সংস্করণে আমি আমার উত্তরে উল্লেখ করা সমস্যাগুলি থাকবে, লাইনগুলি পুনরায় অর্ডার করার এবং ম্যাংলেড আউটপুট (বিশেষত দীর্ঘ লাইনের সাথে) ঝুঁকির বিষয়ে।
গিলস

আমি এটি চেষ্টা করেছিলাম, এবং এটি কার্যকর হয়নি।
মাইকেল

seterrএকটি স্বতন্ত্র স্ক্রিপ্ট হতে হবে, একটি ফাংশন নয়।
গিলস

4

মাইক Schiraldi দেখি Hilite যা একটি সময়ে এক কমান্ডের জন্য এই আছে। আমার নিজের গুশ এটি পুরো অধিবেশনটির জন্য করে তবে এর মধ্যে আরও অনেকগুলি বৈশিষ্ট্য / আইডিয়াসিন্যাস রয়েছে যা আপনি নাও চান।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.