एक प्रोग्राम कैसे तय करता है कि रंगीन आउटपुट है या नहीं?


17

जब मैं एक टर्मिनल से एक कमांड निष्पादित करता हूं जो रंगीन आउटपुट (जैसे lsया gcc) प्रिंट करता है , तो रंगीन आउटपुट प्रिंट होता है। मेरी समझ से, यह प्रक्रिया वास्तव में ANSI एस्केप कोड्स को आउटपुट कर रही है , और टर्मिनल रंग को प्रारूपित करता है।

हालाँकि, अगर मैं उसी प्रक्रिया को किसी अन्य प्रक्रिया द्वारा निष्पादित करता हूं (एक कस्टम सी एप्लिकेशन को कहता है) और आउटपुट को एप्लिकेशन के स्वयं के आउटपुट पर रीडायरेक्ट करता है, तो ये रंग बने नहीं रहते हैं।

एक प्रोग्राम यह कैसे तय करता है कि कलर फॉर्मेट के साथ टेक्स्ट को आउटपुट करना है या नहीं? क्या कुछ पर्यावरण चर है?

जवाबों:


25

इस तरह के अधिकांश कार्यक्रम डिफ़ॉल्ट रूप से टर्मिनल के लिए केवल रंग कोड का उत्पादन करते हैं; वे यह देखने के लिए जांच करते हैं कि क्या उनका आउटपुट एक TTY है, का उपयोग करके isatty(3)। इस व्यवहार को ओवरराइड करने के लिए आमतौर पर विकल्प होते हैं: सभी मामलों में रंगों को अक्षम करें, या सभी मामलों में रंगों को सक्षम करें। उदाहरण के लिए जीएनयू grepके लिए, --color=neverरंगों को निष्क्रिय करता है और --color=alwaysउन्हें सक्षम बनाता है।

शेल में आप -t testऑपरेटर का उपयोग करके एक ही परीक्षण कर सकते हैं : [ -t 1 ]केवल तभी सफल होगा जब मानक आउटपुट एक टर्मिनल है।


क्या शुरू किए गए एप्लिकेशन को ट्रिक करने का कोई तरीका है जो प्रक्रिया एक छोटा है?
क्रिस स्मिथ

4
पहले से ही chix13523 unix.stackexchange.com/questions/249723 पर पूछा और उत्तर दिया गया । टिप्पणियाँ वास्तव में वैसे सवालों के अनुसरण की जगह नहीं हैं।
JdeBP

1
@ chris13524 JdeBP का लिंक देखें; आप कई मामलों में प्रोग्राम को आउटपुट कोड के लिए बाध्य कर सकते हैं (मेरे अपडेट किए गए उत्तर देखें)।
स्टीफन किट

13

क्या कुछ पर्यावरण चर है?

हाँ। यह TERMपर्यावरण चर है। ऐसा इसलिए है क्योंकि कई चीजें हैं जो निर्णय प्रक्रिया के हिस्से के रूप में उपयोग की जाती हैं।

यहां सामान्यीकरण करना मुश्किल है, क्योंकि सभी कार्यक्रम एक ही निर्णय प्रवाह पर सहमत नहीं हैं। वास्तव में grep, GNU , जिसका उल्लेख एम। किट के उत्तर में किया गया है, बाहरी रूप से एक अच्छा उदाहरण है जो अप्रत्याशित परिणामों के साथ कुछ असामान्य निर्णय प्रक्रिया का उपयोग करता है। बहुत सामान्य शब्दों में, इसलिए:

  • मानक आउटपुट टर्मिनल डिवाइस होना चाहिए, जैसा कि निर्धारित किया गया है isatty()
  • कार्यक्रम टर्मपैक / टर्मोफ डेटाबेस में टर्मिनल प्रकार के लिए रिकॉर्ड देखने में सक्षम होना चाहिए।
  • इसलिए ऊपर देखने के लिए एक टर्मिनल प्रकार होना चाहिएTERMवातावरण चर मौजूद होना चाहिए और अपने मूल्य एक डेटाबेस रिकॉर्ड से मेल खाना चाहिए।
  • इसलिए एक टर्मोफ़ / टर्मकैप डेटाबेस होना चाहिए। सबसिस्टम के कुछ कार्यान्वयन पर, TERMCAPपर्यावरण चर का उपयोग करके टर्मपैक डेटाबेस का स्थान निर्दिष्ट किया जा सकता है । तो कुछ कार्यान्वयन पर एक दूसरा वातावरण चर है।
  • टर्मकैप / टर्मऑफ़ रिकॉर्ड को यह बताना होगा कि टर्मिनल प्रकार रंगों का समर्थन करता है। max_colorsTermfo में एक क्षेत्र है। यह उन टर्मिनल प्रकारों के लिए सेट नहीं है जिनमें वास्तव में रंग क्षमताएं नहीं हैं। वास्तव में, एक टर्मोफ कन्वेंशन है कि हर कोलॉइरेबल टर्मिनल प्रकार के लिए एक और रिकॉर्ड है -mया -monoनाम के साथ जोड़ा गया है जिसमें कोई रंग क्षमता नहीं है।
  • रंग बदलने के लिए प्रोग्राम के लिए रास्ता प्रदान करना चाहिए। Termfo में फ़ील्ड्स set_a_foregroundऔर set_a_backgroundफ़ील्ड्स हैं ।

यह सिर्फ जाँच से थोड़ा अधिक जटिल है isatty()। इसे कई चीजों से और जटिल बनाया गया है:

  • कुछ एप्लिकेशन कमांड-लाइन विकल्प या कॉन्फ़िगरेशन फ़्लैग जोड़ते हैं जो isatty()चेक को ओवरराइड करते हैं , ताकि प्रोग्राम हमेशा या कभी भी यह मानें कि इसके आउटपुट के रूप में इसका (colourable) टर्मिनल है। उदाहरण के लिए:
    • GNU lsमें --colorकमांड-लाइन विकल्प है।
    • बीएसडी (इसकी अनुपस्थिति अर्थ कभी नहीं ) और (इसकी उपस्थिति का अर्थ हमेशा ) पर्यावरण चर को lsदेखता है , और कमांड-लाइन विकल्प को भी स्पोर्ट करता है।CLICOLORCLICOLOR_FORCE-G
  • कुछ एप्लिकेशन टर्मकैप / टर्मफो का उपयोग नहीं करते हैं और मूल्य के लिए कठोर प्रतिक्रियाएं हैं TERM
  • सभी टर्मिनल ईसीएमए -48 या आईएसओ 8613-6 एसजीआर अनुक्रमों का उपयोग नहीं करते हैं, जो कि रंग बदलने के लिए थोड़ा गलत नाम "एएनएसआई एस्केप अनुक्रम" हैं। Termcap / termfo तंत्र वास्तव में सटीक नियंत्रण अनुक्रमों के प्रत्यक्ष ज्ञान से अनुप्रयोगों को इन्सुलेट करने के लिए डिज़ाइन किया गया है। (इसके अलावा, एक तर्क दिया जा रहा है कि कोई भी ISO 8613-6 SGR दृश्यों का उपयोग नहीं करता है, क्योंकि हर कोई RGB रंग SGR अनुक्रमों के लिए सीमांकक के रूप में अर्ध-बृहदान्त्र का उपयोग करने की बग पर सहमत है । मानक वास्तव में बृहदान्त्र को निर्दिष्ट करता है।

जैसा कि उल्लेख किया गया है, जीएनयू grepवास्तव में इनमें से कुछ अतिरिक्त जटिलताओं का प्रदर्शन करता है। यह टर्मकैप / टर्मऑफ़ से परामर्श नहीं करता है, नियंत्रण अनुक्रमों को उत्सर्जन करने के लिए हार्डवियर्स करता है, और TERMपर्यावरण चर के लिए एक प्रतिक्रिया देता है ।

इसके लिनक्स / यूनिक्स पोर्ट में यह कोड होता है , जो केवल कोलोरिज़ेशन को सक्षम करता है जब TERMपर्यावरण चर मौजूद होता है और इसका मान हार्डवार्ड नाम से मेल नहीं खाता है dumb:

पूर्णांक
should_colorize (शून्य)
{
  char const * t = getenv ("TERM");
  वापसी t && strcmp (टी, "गूंगा")! = 0;
}

यहां तक ​​कि अगर आपका TERMहै xterm-mono, तो जीएनयू grepरंगों का उत्सर्जन करने का फैसला करेगा, भले ही अन्य कार्यक्रम जैसे कि vimनहीं होगा।

इसके Win32 पोर्ट में यह कोड है , जो कि कोलोरिज़ेशन को सक्षम करता है जब TERMपर्यावरण चर मौजूद नहीं होता है या जब यह मौजूद होता है और इसका मान हार्डवेयर्ड नाम से मेल नहीं खाता है dumb:

पूर्णांक
should_colorize (शून्य)
{
  char const * t = getenv ("TERM");
  वापसी ! (t && strcmp (t, "dumb") == 0);
}

grepरंग के साथ GNU की समस्याएं

ग्नू grepका कोलोरिज़ेशन वास्तव में कुख्यात है। क्योंकि यह वास्तव में टर्मिनल आउटपुट के निर्माण का एक उचित काम नहीं करता है, बल्कि व्यर्थ की उम्मीद में इसके आउटपुट में विभिन्न बिंदुओं पर कुछ कठोर नियंत्रण अनुक्रमों में सिर्फ दोष देता है जो कि काफी अच्छा है, यह वास्तव में कुछ परिस्थितियों में गलत आउटपुट प्रदर्शित करता है।

ये हालात ऐसे हैं, जहां उसे कुछ ऐसा करना पड़ता है, जो टर्मिनल के दाहिने हाथ से होता है। प्रोग्राम जो टर्मिनल आउटपुट को ठीक से करते हैं, उन्हें स्वचालित सही मार्जिन के लिए जिम्मेदार होना चाहिए। मामूली संभावना के अलावा कि टर्मिनल उनके पास नहीं हो सकता है ( auto_right_marginटर्मिन में फ़ील्ड), टर्मिनलों का व्यवहार जो स्वचालित रूप से सही हाशिये का है, वे अक्सर लंबित लाइन रैप के DEC VT मिसाल का पालन करते हैं । GNU grepइसके लिए जिम्मेदार नहीं है, भोलेपन से तत्काल लाइन रैप की उम्मीद करते हैं , और इसका रंगीन आउटपुट गलत हो जाता है।

रंगीन आउटपुट एक साधारण चीज नहीं है।

आगे की पढाई


2
जैसा कि मैं समझता हूं कि ओपी व्यवहार में बदलाव के बारे में पूछ रहा है जब आउटपुट पुनर्निर्देशित होता है; $TERMयह नहीं समझाता। (आपका जवाब सामान्य रूप से दिलचस्प है, लेकिन मुझे नहीं लगता कि यह सवाल को संबोधित करता है ...)
स्टीफन किट

बहुत ही रोचक। मैं इस तरह से एक अवलोकन चाह रहा हूं कि कैसे प्रोग्राम (या बस "निर्णय") की खोज करें कि कुछ महीनों के लिए टर्मिनलों की क्षमता क्या है। इससे यह भी पता चलता है कि इसका अवलोकन इस तरह से करना कठिन क्यों है - क्योंकि प्रत्येक कार्यक्रम इसे थोड़ा अलग तरीके से करने लगता है।
the_velour_fog

किस बारे में एक व्याख्या लंबित लाइन रैप और तत्काल लाइन रैप एक उदाहरण अंतर प्रदर्शन के साथ मतलब एक साथ अच्छा होगा।
मच्छी जूल

0

unbufferआदेश से उम्मीद पैकेज de-जोड़ों पहला कार्यक्रम से उत्पादन और दूसरे कार्यक्रम के लिए इनपुट।

आप इसे इस तरह उपयोग करेंगे:

unbuffer myshellscript.sh | grep value

मैं इसका उपयोग हर समय आंसरशीट और एक होमब्रेव्ड सेटी स्क्रिप्ट के साथ करता हूं ताकि मैं टर्मिनल पर रंग आउटपुट देख सकूं , जबकि लॉग फाइल को सामान्य (गैर-रंगीन) आउटपुट के साथ छोड़ रहा हूं।

unbuffer ansible-playbook myplaybook.yml | ctee /var/log/ansible/run-$( date "+%F" ).log
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.