बैश दो शेल प्रॉम्प्ट लिखने का प्रयास करता है?


11

मैं शैक्षिक उद्देश्यों के लिए, टर्मिनल से जुड़ी चल रही बैश प्रक्रिया के स्ट्रेस आउटपुट को देख रहा हूं।

मेरी बैश प्रक्रिया में PID 2883 है।

मैं अंकित करता हुँ

[OP@localhost ~]$ strace -e trace=openat,read,write,fork,vfork,clone,execve -p 2883 2> bash.strace

एक टर्मिनल में। मैं तब अपनी बैश प्रक्रिया में जाता हूं, और निम्नलिखित बातचीत होती है:

[OP@localhost ~]$ ls

आउटपुट को देखते हुए, मैं देखता हूं

strace: Process 2883 attached
read(0, "l", 1)                         = 1
write(2, "l", 1)                        = 1
read(0, "s", 1)                         = 1
write(2, "s", 1)                        = 1
read(0, "\r", 1)                        = 1
write(2, "\n", 1)                       = 1
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fec6b1d8e50) = 3917
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3917, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
write(1, "\33]0;OP@localhost:~\7", 23) = 23
write(2, "[OP@localhost ~]$ ", 22)  = 22
...

मैं आखिरी दो लाइनों में उलझन में हूं। ऐसा प्रतीत होता है कि बैश दो शेल प्रॉम्प्ट लिखने का प्रयास कर रहे हैं? यहाँ क्या चल रहा है?

जवाबों:


24

<ESC>]0;अनुक्रम (के रूप में दिखाया \33]0;strace से) टर्मिनल विंडो शीर्षक सेट करने के भागने अनुक्रम है। यह बीईएल चरित्र ( \7) के साथ समाप्त हो गया है , इसलिए पहले writeविंडो शीर्षक सेट करता है। दूसरा वास्तविक प्रॉम्प्ट को प्रिंट करता है। ध्यान दें कि भागने के क्रम के अलावा, वे बिल्कुल समान नहीं हैं। [..]विंडो शीर्षक नहीं होने पर प्रांप्ट में एक आसपास होता है।

हम यह भी देख सकते हैं कि पहला लेखन stdout (fd 1, पहला तर्क write()), और दूसरा stderr को जाता है। बैश स्टेटर को संकेत देता है, इसलिए पहला लेखन कहीं और से आता है। वह शायद कहीं है PROMPT_COMMAND, जैसे देब की डिफॉल्ट स्टार्टअप स्क्रिप्ट्स बैश के लिए। वहाँ कुछ इस तरह से है:

case "$TERM" in
xterm*|rxvt*)
    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
    ;;
*)
    ;;
esac

यह सेट करता है कि PROMPT_COMMANDयदि चल रहा है xtermया rxvt, जो उस अनुक्रम से बचना चाहिए।


क्या आप जानते हैं कि एक समय में एक पंक्ति में पढ़ने के बजाय, चरित्र द्वारा चरित्रों को पढ़ना क्यों प्रतीत होता है? इसके अलावा, bash ने स्टैडआउट को "l" और "s" क्यों लिखा है? अगर मैं इसी तरह की धारा लगाता हूं cat, तो दो अंतर होते हैं: यह इनपुट लाइन को लाइन से पढ़ता है, और जब यह अपने इनपुट को वापस करने के लिए प्रतिध्वनित करता है, तो मैं इनपुट को दो बार देखता हूं (एक बार जब मैं टाइप करता हूं, और एक बार जब बिल्ली इसे खोदती है)।
एक्सट्रीमैक्स 5

@ extremeaxe5, यह मूल रूप से है क्योंकि बैश (या बल्कि रीडलाइन लाइब्रेरी) टर्मिनल द्वारा किए गए बल्कि सीमित प्रसंस्करण पर निर्भर होने के बजाय, सभी कमांड लाइन प्रसंस्करण को स्वयं संभालता है। यह तय करने के लिए तुरंत इनपुट प्राप्त करना है कि कब क्या करना है जैसे कि एक TAB चरित्र या ^A(Ctrl-A) या विभिन्न विशेष वर्ण दबाए जाते हैं। इसके अलावा, यह टर्मिनल की गूंज को बंद कर देता है, ताकि यह तय हो सके कि प्रत्येक विशेष इनपुट चरित्र के लिए क्या उत्पादन किया जाए (फिर से, TAB आमतौर पर एक TAB का उत्पादन नहीं करता है।) catइसमें से कोई भी नहीं करता है। यदि आप इसे चलाते हैं dash, तो चलाने का प्रयास करें , जो किसी भी कमांड लाइन से निपटने का काम नहीं करता है।
ilkachachu

दरअसल, बैश read()एक समय में केवल एक बाइट को पढ़ने के लिए कहता है, क्योंकि यह एक नई पंक्ति नहीं पढ़ सकता है। नई लाइन के कारण यह एक बाहरी प्रोग्राम को चला सकता है, जो उसी इनपुट से भी पढ़ सकता है। (और वह कार्यक्रम नई पंक्ति के बाद किसी भी वर्ण को पढ़ने में सक्षम होना चाहिए।) अगर उसे इस बात की परवाह नहीं थी, तो वह read()बड़ी सीमा के साथ कॉल कर सकता है, और कच्चे मोड में टर्मिनल के साथ, यह अभी भी आमतौर पर इनपुट प्राप्त करेगा। एक समय में एक चरित्र। (यह होगा कि इनपुट वर्ण कितनी तेजी से आएंगे और प्रक्रिया कैसे निर्धारित की गई है।)
ilkachachu

आपकी दूसरी टिप्पणी केवल सच प्रतीत होती है क्योंकि बैश कमांड-लाइन को स्वयं संभालता है।
एक्सट्रीमैक्स 5

@ extremeaxe5, ठीक है, हाँ, मैं यह मान रहा था, क्योंकि यह वैसे भी सामान्य मामला है। लेकिन, भले ही शेल टर्मिनल की लाइन एडिटिंग पर निर्भर हो, लेकिन टाइमिंग अभी भी एक मुद्दा हो सकता है। यदि दो पंक्तियों को त्वरित उत्तराधिकार में भेजा गया था (डेटा चिपकाने के बारे में सोचें), और सिस्टम को पर्याप्त लोड किया गया था, तो शेल तुरंत शेड्यूल नहीं किया जाएगा (या इससे भी बदतर, शेल को रोक दिया गया था), तो read()बड़े बफर के साथ अभी भी दोनों लाइनों को वापस कर सकते हैं वही कॉल। मुझे नहीं लगता कि कोई गारंटी है कि हमेशा पकाया मोड में सिर्फ एक पंक्ति वापस आ read()जाएगी ।
ilkachachu
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.