हम कैसे जान सकते हैं कि छद्म टर्मिनल डिवाइस के दूसरे छोर पर कौन है?


26

अगर मैं एक:

echo foo > /dev/pts/12

कुछ प्रक्रिया यह पढ़ेगी कि foo\nइसकी फाइल डिस्क्रिप्टर से मास्टर साइड में है।

क्या यह पता लगाने का एक तरीका है कि (उन) प्रक्रिया (तों) क्या है (हैं)?

या दूसरे शब्दों में, मैं कैसे पता लगा सकता हूं कि कौन सा xterm / sshd / script / screen / tmux / उम्मीद / socat ... के दूसरे छोर पर है /dev/pts/12?

lsof /dev/ptmxमुझे उन प्रक्रियाओं के बारे में बताएंगे, जिनके पास किसी भी प्रकार के मास्टर के फ़ाइल डिस्क्रिप्टर हैं। एक प्रक्रिया स्वयं ptsname()( TIOCGPTNioctl) मास्टर साइड में अपने स्वयं के fd के आधार पर दास डिवाइस का पता लगाने के लिए उपयोग कर सकती है, इसलिए मैं इसका उपयोग कर सकता हूं:

gdb --batch --pid "$the_pid" -ex "print ptsname($the_fd)"

lsofउस मैपिंग को बनाने के लिए प्रत्येक पीआईडी ​​/ एफडी द्वारा लौटाया गया , लेकिन क्या उस जानकारी को प्राप्त करने के लिए अधिक प्रत्यक्ष, विश्वसनीय और कम दखल देने वाला तरीका है?


क्या ये वही है जो तुम चाहते हो? sudo find /proc/*/fd/0 -ls | grep '/dev/pts/4', /proc/PIDआउटपुट के रूप में पीआईडी ​​( ) की सूची प्रदान करेगा ।
स्लम

@ एसएलएम, नहीं, दूसरे शब्दों में, मैं यह पता लगाना चाहता हूं कि कौन सा xterm / sshd / script / screen / tmux / उम्मीद / socat ... के दूसरे छोर पर है /dev/pts/4। आमतौर पर, यह उन प्रक्रियाओं का एक सामान्य पूर्वज होगा जो /dev/pts/4खुले हैं, लेकिन जरूरी नहीं है।
स्टीफन चेज़लस

1
यह सॉकेट्स के साथ भी बदतर है - आपको कर्नेल डिबगर की आवश्यकता है!
गिल्स एसओ- बुराई को रोकें '

1
@Falsenames - मैंने प्रश्न का अर्थ समझा - शायद गलत तरीके से - डेटा पढ़ने के लिए कौन सी प्रक्रिया पारित की जाती है - जैसे कि टर्मिनल में पहले शेल का आह्वान किया गया है - लेकिन वास्तव में कौन सी प्रक्रिया इसे मास्टर की ओर से पढ़ती है। उदाहरण के लिए, यदि मैं एक शेल लॉन्च करता हूं, तो screenयह है screenकि डिवाइस के जीवन के लिए पेंटी स्लेव को आवंटित और सक्रिय रूप से प्रबंधित करता है, लेकिन - जैसा कि, मुझे लगता है - शेल को उस tty और इसलिए, के रूप में प्रक्रिया-नेता बनाया गया है आउटपुट शो, आपको मिलता है bashया जो कुछ भी psनहीं है screen। मैंने कुछ xtermsपीठ के xtermआधार पर पता लगाया /proc/locksलेकिन यह ढीली थी।
मिकसेर

जवाबों:


3

सबसे पहले मैंने जानकारी के आधार पर पिड पर कुछ xtermएस वापस ट्रेस करने की कोशिश की जो xtermमुझे मिली, /proc/locksलेकिन यह ढीली थी। मेरा मतलब है, यह काम किया है, मुझे लगता है, लेकिन यह सबसे अच्छी स्थिति में था - मैं पूरी तरह से उस जानकारी को पूरी तरह से नहीं समझता हूं जो फ़ाइल प्रदान करती है और केवल वही मिलान कर रही थी जो इसकी सामग्री और ज्ञात टर्मिनल प्रक्रियाओं के बीच मेल खाती थी।

फिर मैंने पेंटी के बीच lsof/straceएक सक्रिय write/talkप्रक्रिया को देखने की कोशिश की । मैंने पहले कभी भी या तो कार्यक्रम का उपयोग नहीं किया था, लेकिन वे भरोसा करते हैं utmp। अगर मेरी लक्षित पीटी में utmpउन दोनों कारणों के लिए कोई प्रविष्टि नहीं थी , जो दोनों ने स्वीकार किया था कि यह अस्तित्व में है। हो सकता है कि इसके आसपास एक रास्ता हो, लेकिन मैं इसे छोड़ने के लिए काफी उलझन में था।

मैंने udevadm136 और 128 प्रमुख नंबर डिवाइस नोड्स के साथ कुछ खोज करने की कोशिश की , ptsऔर इसके लिए ptmक्रमशः विज्ञापन दिया गया /proc/tty/drivers, लेकिन मुझे उस टूल के साथ किसी भी बहुत उपयोगी अनुभव की कमी है और एक बार फिर कुछ भी नहीं हुआ। दिलचस्प है, हालांकि, मैंने देखा कि :minदोनों डिवाइस प्रकारों के लिए सीमा एक चौंका देने वाली सूची में सूचीबद्ध थी 0-1048575

यह तब तक नहीं था जब तक मैं इस कर्नेल डॉक पर दोबारा गौर नहीं करता कि मैं इस समस्या के बारे में सोचना शुरू कर देता mount, हालांकि। मैंने पहले भी कई बार पढ़ा था लेकिन जब उस पंक्ति में निरंतर शोध ने मुझे इस 2012 /dev/ptsपैचसेट तक पहुँचाया तो मुझे एक विचार आया:

sudo fuser -v /dev/ptmx

मैंने सोचा कि मैं आमतौर पर प्रक्रियाओं को सहयोगी के साथ क्या उपयोग करता हूं mount? और निश्चित रूप से पर्याप्त:

                     USER        PID ACCESS COMMAND
/dev/ptmx:           root      410   F.... kmscon
                     mikeserv  710   F.... terminology

इसलिए उस जानकारी के साथ मैं कर सकता हूँ, उदाहरण के लिए terminology:

sudo sh -c '${cmd:=grep rchar /proc/410/io} && printf 1 >/dev/pts/0 && $cmd'
###OUTPUT###
rchar: 667991010
rchar: 667991011

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

sudo sh -c 'ss -oep | grep "$(printf "pid=%s\n" $(fuser /dev/ptmx))"'

इसलिए मैंने इसे थोड़ा और स्पष्ट परीक्षण के साथ स्थापित किया, वास्तव में:

sudo sh <<\CMD
    chkio() {
        read io io <$1
        dd bs=1 count=$$ </dev/zero >$2 2>/dev/null
        return $((($(read io io <$1; echo $io)-io)!=$$))
    }
    for pts in /dev/pts/[0-9]* ; do
        for ptm in $(fuser /dev/ptmx 2>/dev/null)
            do chkio /proc/$ptm/io $pts && break
        done && set -- "$@" "$ptm owns $pts"
    done
    printf %s\\n "$@"
 CMD

यह प्रत्येक pty के लिए $$num \0null बाइट को प्रिंट करता है और प्रत्येक मास्टर प्रक्रिया के पिछले चेक के विरुद्ध io की जाँच करता है। यदि अंतर है $$तो यह पीट को पीटीआई के साथ जोड़ता है। यह ज्यादातर काम करता है। मेरा मतलब है, मेरे लिए, यह रिटर्न:

410 owns /dev/pts/0
410 owns /dev/pts/1
710 owns /dev/pts/2

जो सही है, लेकिन, जाहिर है, यह थोड़ा सा है। मेरा मतलब है, अगर उन लोगों में से एक उस समय डेटा के एक समूह में पढ़ रहा था, तो यह शायद याद होगा। मैं यह जानने की कोशिश कर रहा हूं sttyकि स्टॉप बिट को पहले भेजने के लिए किसी अन्य प्रकार के मोड को कैसे बदलना है या ऐसा कुछ है ताकि मैं इसे ठीक कर सकूं।


2

यदि आप सिर्फ इस बात की तलाश कर रहे हैं कि कनेक्शन का मालिक कौन है और वे कहां से जुड़े हैं, तो कौन कमांड अच्छी तरह से काम करेगा।

$ who
falsenames   tty8         Jun 13 16:54 (:0)
falsenames   pts/0        Jun 16 11:18 (:0)
falsenames   pts/1        Jun 16 12:59 (:0)
falsenames   pts/2        Jun 16 13:46 (:0)
falsenames   pts/3        Jun 16 14:10 (:0)
falsenames   pts/4        Jun 16 16:41 (:0)

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

$ w
 16:44:09 up 2 days, 23:51,  6 users,  load average: 0.26, 0.98, 1.25
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
falsenames   tty8     :0               Fri16    2days 53:36   0.59s x-session-manager
falsenames   pts/0    :0               11:18    5:25m  1:10   1:10  synergys -a 10.23.8.245 -c .synergy.conf -f -d DEBUG
falsenames   pts/1    :0               12:59    3:44m  0.05s  0.05s bash
falsenames   pts/2    :0               13:46    2:52m  0.11s  0.11s bash
falsenames   pts/3    :0               14:10    2:17   0.07s  0.07s bash
falsenames   pts/4    :0               16:41    1.00s  0.04s  0.00s w

और pids पाने के लिए, एक ps को tty सेशन तक सीमित करें जिसे आप देख रहे हैं। बूट करने के लिए पूरी तरह से विनीत।

$ ps -t pts/0 --forest 
  PID TTY          TIME CMD
23808 pts/0    00:00:00 bash
23902 pts/0    00:03:27  \_ synergys

ध्यान दें, यह समय के आधार पर लाल झुंडों को जन्म दे सकता है। लेकिन यह एक अच्छी जगह है।

$ tty
/dev/pts/4
$ ps -t pts/4 --forest
  PID TTY          TIME CMD
27479 pts/4    00:00:00 bash
 3232 pts/4    00:00:00  \_ ps
27634 pts/4    00:00:00 dbus-launch

धन्यवाद, लेकिन यह वह नहीं है जिसकी मुझे तलाश है। उदाहरण के लिए, मैं टर्मिनल एप्लिकेशन (Xterm / सूक्ति-टर्मिनल ...) के उस पृष्ठ को खोजना चाहता हूं /dev/pts/4, जहां आप उस wकमांड को चलाते हैं ।
स्टीफन चेज़लस

क्षमा करें, जब मैंने पहली बार स्कैन किया तो पूरी तरह से पिड भाग छूट गया। मुझे लगा कि आप केवल अंतिम प्रक्रिया नाम जानना चाहते हैं।
फर्ल्सनम्स

2

क्यूमू के साथ मुझे भी यही समस्या थी, और मुझे आखिरकार एक बहुत बुरा समाधान मिला (लेकिन फिर भी एक समाधान): प्रक्रिया स्मृति को पार्स करना।

यह यहां काम कर रहा है क्योंकि मुझे पता है कि qemu एक विशिष्ट प्रारूप के साथ एक स्ट्रिंग में दूरस्थ pts को संग्रहीत कर रहा है और ढेर पर आवंटित किया गया है। हो सकता है कि यह अन्य स्थितियों में भी कुछ बदलावों के साथ और फ़्यूज़र आउटपुट से पिड का पुन: उपयोग करके (अन्य उत्तर की जाँच) कर सकता है।

यहां से कोड को अनुकूलित किया गया है

#! /usr/bin/env python

import sys
pid = sys.argv[1]

import re
maps_file = open("/proc/" + pid + "/maps", 'r')
mem_file = open("/proc/" + pid + "/mem", 'r', 0)
for line in maps_file.readlines():
    # You may want to remove the 'heap' part to search all RAM
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r]).*\[heap\]', line)
    if m and m.group(3) == 'r':
        start = int(m.group(1), 16)
        end = int(m.group(2), 16)
        mem_file.seek(start)
        chunk = mem_file.read(end - start)
        # You may want to adapt this one to reduce false matches
        idx = chunk.find("/dev/pts/")
        if idx != -1:
            end = chunk.find("\0", idx)
            print chunk[idx:end]
maps_file.close()
mem_file.close()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.