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