कंट्रोलिंग टर्मिनल का वास्तविक नाम कैसे प्राप्त करें?


13

पाथनेम के रूप में कंट्रोलिंग टर्मिनल का असली नाम (यदि कोई है, तो कोई और त्रुटि है) कैसे मिल सकता है?

"वास्तविक नाम" से मेरा अभिप्राय है /dev/tty, जिसका उपयोग अन्य मनमानी प्रक्रियाओं द्वारा एक ही टर्मिनल के संदर्भ में नहीं किया जा सकता है। मैं उत्तर को एक सरल शेल कोड के रूप में पसंद करता हूं (यदि संभव हो तो नीचे दिए गए उदाहरण की तरह), अन्यथा सी फ़ंक्शन के रूप में।

ध्यान दें कि मानक इनपुट पुनर्निर्देशित होने पर भी यह काम करना चाहिए, ताकि ttyउपयोगिता का उपयोग न किया जा सके: किसी को not a ttyऐसे मामले में त्रुटि मिलेगी , क्योंकि ttyमानक इनपुट से जुड़े टर्मिनल के फ़ाइल नाम को सिर्फ प्रिंट करता है।

लिनक्स के तहत, एक का उपयोग कर सकते हैं:

echo "/dev/`ps -p $$ -o tty | tail -n 1`"

लेकिन यह पोर्टेबल नहीं है, क्योंकि POSIX के अनुसार, टर्मिनल नाम का प्रारूप अनिर्दिष्ट है

सी कार्यों के बारे में, ctermid (NULL)रिटर्न /dev/tty, जो यहां बेकार है।

नोट:zsh प्रलेखन के अनुसार , एक करने में सक्षम होना चाहिए

zsh -c 'echo $TTY'

लेकिन यह वर्तमान में (संस्करण 5.0.7) विफल रहता है जब मानक इनपुट और मानक आउटपुट दोनों को पुनर्निर्देशित किया जाता है:

$ zsh -c 'echo $TTY > /dev/tty' < /dev/null
/dev/pts/9
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null > /dev/null
/dev/tty

@ मोटरसाइकल मुझे लगता है कि psसमाधान अधिकांश प्रणालियों को कवर whoकरता है (और अधिक मदद नहीं करता है ps), संभवतः अकेले पहचानकर्ता को संभालने के लिए थोड़ा और कोड के साथ (जैसे "04")। मैं सोच रहा था कि क्या कोई और भी पोर्टेबल समाधान था।
vinc17

यह पूर्व-युग्मित सेटों के साथ करना पड़ सकता है - पुराने bsd -style pty जोड़े साथ ही, शायद। सभी ptys UNIX 98 प्रकार के नहीं हैं। वैसे भी, से man xterm: -Sccn यह विकल्प की अनुमति देता है xterm/ एक मौजूदा कार्यक्रम के लिए एक मैं के रूप में प्रयोग की जाने वाली ओ चैनल ... विकल्प मान दास मोड में उपयोग करने के लिए एक प्राइवेट के नाम के कुछ अक्षर, प्लस विरासत में मिला fd संख्या है। यदि विकल्प में "/" वर्ण है, तो यह fd से pty नाम का परिसीमन करता है।
दोपहर

@mikeserv ध्यान दें कि समाधान साथ काम नहीं करता psसे बिजीबॉक्स (जो एंड्रॉयड, BTW द्वारा प्रयोग किया जाता है), तब भी जीएनयू / लिनक्स के तहत। "क्या आप xtermइसे संभाल सकते हैं " से क्या मतलब है 04?
vinc17

busyboxPOSIX-अनुरूप नहीं है। toyboxहालाँकि, बहुत अच्छा करता है।
दोपहर

जवाबों:


8

"कंट्रोलिंग टर्मिनल" उर्फ। ctty, से "distincted है टर्मिनल एक प्रक्रिया के साथ बातचीत कर रहा है"।

शेट्टी का मार्ग प्राप्त करने का मानक तरीका ctermid (3) है। इसे कॉल करने पर, 10 जारी करने के बाद से फ़्रीबीडी में, एक वास्तविक पथ को देखा जाता है [1], जबकि पुराने फ़्रीबल्ड और ग्लिबक कार्यान्वयन [2] बिना शर्त "" / देव / ट्टी "देता है।

ps (1) लाइनक्स से 3.2.8 पैकेज की खरीद करता है, / proc / * / stat [3] में संख्यात्मक प्रविष्टि को पढ़ता है , और फिर सिस्टम समर्थन की कमी के कारण [4, 5] अनुमान लगाकर पथनाम को आंशिक रूप से घटा देता है [6] ।

हालाँकि अगर हम शेट्टी में कड़ाई से दिलचस्पी नहीं रखते हैं लेकिन stdio, tty (1) से जुड़ा कोई भी टर्मिनल स्टड से जुड़े टर्मिनल पथ को प्रिंट करता है, जो ttyname(fileno(stdin))c के समान है , और एक विकल्प है readlink /proc/self/fd/0


बिना शर्त "/ देव / tty" व्यवहार के बारे में कम महत्वपूर्ण विचार: चश्मा केवल यह कहता है कि स्ट्रिंग को ctermid द्वारा लौटाया जाता है "जब एक पथ नाम के रूप में उपयोग किया जाता है, तो वर्तमान नियंत्रण टर्मिनल का संदर्भ लें", कुछ सीधे के बजाय "वर्तमान का पथ नाम है" नियंत्रण टर्मिनल "। यह समझा जा सकता है कि "/ dev / tty" नियंत्रण टर्मिनल नहीं है, लेकिन केवल नियंत्रण टर्मिनल का संदर्भ लें यदि वही प्रक्रिया खुले (3)। इस प्रकार "एक टर्मिनल अधिकतम एक सत्र के लिए शेट्टी हो सकता है" नियम का उल्लंघन नहीं करता है [7]।

एक और परिणाम यह है कि जब मैं किसी भी नियंत्रित टर्मिनल के बिना होता हूं, तो ctermid विफल नहीं होता है - इस तरह की असफलता को ऐनक द्वारा अनुमति दी जाती है [8] -, इसलिए केवल मैं अपने शेट्टीलेसनेस से अवगत हो सकता हूं जब तक कि बाद में खुला (3) विफल नहीं होता है। जो ठीक है क्योंकि चश्मा भी खुले (3) कॉलिंग को सफल नहीं कहता है।


यह psमेरे प्रश्न में दिए गए समाधान से अधिक पोर्टेबल नहीं है , क्योंकि सभी ओएस में /procफाइल सिस्टम नहीं है। ध्यान दें कि psस्वयं एक रीडलिंक का उपयोग करता है /proc/self/fd/2(जो काम करता है यहां तक ​​कि मानक त्रुटि को पुनर्निर्देशित किया जाता है)।
vinc17

1
संपादित। और ps रीड / पर / proc / * / fd / 2 शेट्टी को खोजने के लिए नहीं, बल्कि पथ के लिए संख्यात्मक टर्मिनल को मैप करने के लिए पूरक जानकारी लेने के लिए, लिंक देखें [4] [5]।
把 留 在 无 '

1
बहुत बढ़िया संपादन। शेट्टी के बारे में; मैं vinc17 के लिए बात नहीं कर सकता, लेकिन जब आप शायद हमेशा कहीं लिख सकते हैं, तो केवल एक फाइल है जो आपके प्रक्रिया समूह को जीवित रखने के लिए खुली होनी चाहिए।
mikeserv

1
@ vinc17 - अगर आपके पास अपनी शेट्टी पर कोई फ़ाइल डिस्क्रिप्टर खुला है तो आप उन्हें पढ़ सकते हैं ttystderrशायद सबसे अच्छा है क्योंकि यह खुले आर / डब्ल्यू होने का अनुमान है। तो tty <&2
दोपहर

1
यह कि किसी दिए गए टर्मिनल के लिए शेट्टी हो सकती है, जो एक सत्र में ctermid()हमेशा के लिए वापस नहीं आता है "/dev/tty"। यह नाम हमेशा इसे एक्सेस करने वाली प्रक्रिया के कंट्रोलिंग टर्मिनल को संदर्भित करता है , जो सत्र के अनुसार बदलता रहता है। टर्मिनल सत्र विशिष्ट है, लेकिन जिस नाम से इसे एक्सेस किया जाता है उसे होने की आवश्यकता नहीं है।
पेलमेल

5

POSIX कल्पना वास्तव में अपने दांव हेज को नियंत्रित करती है जहां नियंत्रण टर्मिनल का संबंध है, और जो इसे इस प्रकार परिभाषित करता है:

  • टर्मिनल को नियंत्रित करना
    • टर्मिनल का जिक्र करने वाली संभवत: कई विशेष फाइलों में से कौन सा प्रश्न POSIX.1 में संबोधित नहीं किया गया है। पाथनाम /dev/ttyएक प्रक्रिया से जुड़े नियंत्रण टर्मिनल का एक पर्याय है।

यह परिभाषा सूची में है - और यह सब वहाँ है। लेकिन जनरल टर्मिनल इंटरफ़ेस में , कुछ और कहा गया है:

  • एक टर्मिनल अपने नियंत्रण टर्मिनल के रूप में एक प्रक्रिया से संबंधित हो सकता है। एक सत्र की प्रत्येक प्रक्रिया जिसमें एक नियंत्रण टर्मिनल होता है, एक ही नियंत्रण टर्मिनल होता है। एक टर्मिनल अधिकतम एक सत्र के लिए नियंत्रण टर्मिनल हो सकता है। एक सत्र के लिए नियंत्रण टर्मिनल को कार्यान्वयन-परिभाषित तरीके से सत्र के नेता द्वारा आवंटित किया जाता है। यदि किसी सत्र के नेता के पास कोई नियंत्रण टर्मिनल नहीं है, और वह एक टर्मिनल डिवाइस फ़ाइल खोलता है जो पहले से ही O_NOCTTY विकल्प (ओपन () देखें) का उपयोग किए बिना सत्र से संबद्ध नहीं है, तो यह कार्यान्वयन-परिभाषित है कि क्या टर्मिनल सत्र का नियंत्रण टर्मिनल बन जाता है नेता।

  • एक फोर्क () फ़ंक्शन कॉल के दौरान कंट्रोलिंग टर्मिनल को एक बच्चे की प्रक्रिया द्वारा विरासत में मिला है। जब इसके साथ एक नया सत्र बनता है तो एक प्रक्रिया अपने नियंत्रण टर्मिनल को त्याग देती हैsetsid()समारोह; पुराने सत्र में अन्य प्रक्रियाएँ जो इस टर्मिनल के पास थीं क्योंकि उनके नियंत्रण टर्मिनल के पास यह जारी है। सिस्टम में अंतिम फ़ाइल डिस्क्रिप्टर के बंद होने पर (वर्तमान सत्र में है या नहीं) कंट्रोलिंग टर्मिनल के साथ जुड़ा हुआ है, यह अनिर्दिष्ट है कि क्या सभी प्रक्रियाओं में उस टर्मिनल के रूप में उनके नियंत्रण टर्मिनल के पास कोई नियंत्रण टर्मिनल नहीं है। क्या और कैसे एक सत्र के नेता नियंत्रण टर्मिनल को फिर से प्राप्त कर सकते हैं, क्योंकि नियंत्रित टर्मिनल को इस तरह से अनिर्दिष्ट किया गया है। एक प्रक्रिया अपने नियंत्रण टर्मिनल को केवल इसलिए नियंत्रित नहीं करती है कि अगर नियंत्रण के साथ जुड़े इसकी सभी फ़ाइल विवरणकर्ता बंद हो जाते हैं यदि अन्य प्रक्रियाएं इसे खोलना जारी रखती हैं।

वहाँ बहुत कुछ है जो अनिर्दिष्ट है - और ईमानदारी से मुझे लगता है कि यह समझ में आता है। जबकि टर्मिनल एक प्रमुख उपयोगकर्ता इंटरफ़ेस है, यह कुछ मामलों में सभी प्रकार की अन्य चीजें भी है - जैसे वास्तविक हार्डवेयर, या यहां तक ​​कि एक प्रकार का प्रिंटर - लेकिन बहुत सारे मामलों में यह व्यावहारिक रूप से कुछ भी नहीं है - जैसे xtermकि सिर्फ एक एमुलेटर । वहां विशिष्ट होना मुश्किल है - और मुझे नहीं लगता कि यह वैसे भी यूनिक्स के हित में होगा, क्योंकि टर्मिनल यूनिक्स से बहुत अधिक हैं।

वैसे भी, POSIX भी सुंदर iffy है कि कैसे psव्यवहार करना चाहिए जहां शेट्टी का संबंध है।

वहाँ -aस्विच है:

  • टर्मिनलों से जुड़ी सभी प्रक्रियाओं की जानकारी लिखें। कार्यान्वयन इस सूची से सत्र के नेताओं को छोड़ सकता है।

महान। सत्र के नेताओं को छोड़ा जा सकता है। यह बहुत मददगार नहीं है।

और -t:

  • टर्मिनलों में दी गई टर्मिनलों से जुड़ी प्रक्रियाओं की जानकारी लिखें। आवेदन यह सुनिश्चित करेगा कि शब्दावली एक <blank>या अल्पविराम से अलग सूची के रूप में एक तर्क है । कार्यान्वयन-परिभाषित प्रारूप में टर्मिनल पहचानकर्ता दिए जाएंगे ।

... जो एक और लेट-डाउन है। लेकिन यह XSI सिस्टम के बारे में यह कहता है:

  • XSI-अनुरूप सिस्टम पर, उन्हें दो रूपों में से एक में दिया जाएगा: डिवाइस का फ़ाइल नाम (उदाहरण के लिए tty04), या, यदि डिवाइस का फ़ाइल नाम के साथ शुरू होता है tty, तो पात्रों के बाद पहचानकर्ता tty (उदाहरण के लिए, 04)

यह थोड़ा बेहतर है, लेकिन एक रास्ता नहीं है। XSI सिस्टम पर भी -dस्विच है:

  • सत्र के नेताओं को छोड़कर सभी प्रक्रियाओं की जानकारी लिखें।

... जो कम से कम स्पष्ट है। आप -output स्विच को ttyप्रारूप स्ट्रिंग के साथ निर्दिष्ट कर सकते हैं , लेकिन, जैसा कि आपने नोट किया है, इसका आउटपुट प्रारूप कार्यान्वयन-परिभाषित है। फिर भी, मुझे लगता है कि यह जितना अच्छा है उतना अच्छा है। मुझे लगता है कि - बहुत काम के साथ - कुछ अन्य उपयोगिताओं के संयोजन में उपरोक्त स्विच आपको एक बहुत अच्छा बॉलपार्क मिल सकता है। हालांकि काफी ईमानदार होने के लिए, मुझे नहीं पता कि यह आपके लिए कब / कैसे टूटता है - और मैं ऐसी स्थिति की कल्पना नहीं कर पाया हूं जिसमें यह होगा। लेकिन, मुझे लगता है कि अगर हम जोड़ते हैं fuserऔर findहम पथ को सत्यापित कर सकते हैं।

exec 2<>/dev/null
ctty=$(sh -c 'ps -p "$$" -o tty=' <&2)
sid=$(sh -c 'ps -Ao pid= -o tty=|
      grep '"$ctty$"' | 
      grep -Fv "$(ps -do pid=)"'  <&2)
find / -type c -name "*${ctty##*/}*" \
       -exec fuser -uv {} \; 2>&1  |
grep ".*$ctty.*${sid%%"$ctty"*}"

/dev/nullसामान बस पता चलता है जब खोज subshells में से कोई भी 0,1,2 ctty से जुड़ा के किसी भी था कि यह काम कर सकता था। वैसे भी, कि प्रिंट:

/dev/pts/3:          mikeserv   3342 F.... (mikeserv)zsh

अब उपरोक्त को मेरी मशीन पर पूरा रास्ता मिल गया है, और मुझे लगता है कि यह ज्यादातर मामलों में ज्यादातर लोगों के लिए होगा। मैं यह भी सोच सकता हूं कि यह विफल हो सकता है। यह सिर्फ मोटा अनुमान है।

यह संभवत: कई अन्य कारणों से विफल हो सकता है, लेकिन यदि आप एक ऐसी प्रणाली पर हैं, जो सत्र के नेता को सभी विवरणों को शेट्टी को त्यागने की अनुमति देता है और फिर भी वह किनारे पर रहता है, जैसा कि कल्पना की अनुमति देता है, तो यह निश्चित रूप से मदद करने वाला नहीं है। उस ने कहा, मुझे लगता है कि यह ज्यादातर मामलों में बहुत अच्छा अनुमान लगा सकता है।

निश्चित रूप से सबसे आसान काम अगर आप अपने शेट्टी से जुड़ा कोई भी वर्णनकर्ता है ...

tty <&2

...या इसी के समान।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.