लिनक्स पर सॉकेट कनेक्शन का समय कैसे निर्धारित करें


24

मैं सत्यापित कर सकता हूं कि कनेक्शन चालू है:

$ netstat -tn | grep "192.168.2.110"
tcp  0  0 192.168.2.100:10444  192.168.2.110:52639  ESTABLISHED

क्या यह जाँचने का कोई तरीका है कि यह tcp पोर्ट कनेक्शन कितने समय तक जुड़ा (जुड़ा) था?

(नहीं, मेरे पास ऐप लॉग तक नहीं है)

जवाबों:


23

आप निम्नलिखित की कोशिश कर सकते हैं:

  1. विकल्प को $pidजोड़कर कार्यक्रम की पीआईडी ​​(कहना ) प्राप्त करें ।-pnetstat

  2. में उचित पंक्ति की पहचान /proc/net/tcpको देखकर फ़ाइल local_addressऔर / या rem_address(कि वे हेक्स प्रारूप में हैं, विशेष रूप से आईपी पते थोड़ा-endian बाइट क्रम में व्यक्त किया है टिप्पणी) क्षेत्रों, भी सुनिश्चित करें कि stहै 01(के लिए ESTABLISHED);

  3. संबंधित inodeफ़ील्ड पर ध्यान दें (कहें $inode);

  4. कि के लिए खोज inodeमें फ़ाइल वर्णनकर्ता के बीच /proc/$pid/fdऔर अंत में प्रतीकात्मक कड़ी की फ़ाइल उपयोग समय क्वेरी:

    find /proc/$pid/fd -lname "socket:\[$inode\]" -printf %t
    

यह एक गंभीर काम है ... यहां उपरोक्त बिंदुओं को स्वचालित करने के लिए एक स्क्रिप्ट (स्टब) है, इसे दूरस्थ पते की आवश्यकता है और यह सेकंड में सॉकेट अपटाइम प्रिंट करता है :

function suptime() {
    local addr=${1:?Specify the remote IPv4 address}
    local port=${2:?Specify the remote port number}
    # convert the provided address to hex format
    local hex_addr=$(python -c "import socket, struct; print(hex(struct.unpack('<L', socket.inet_aton('$addr'))[0])[2:10].upper().zfill(8))")
    local hex_port=$(python -c "print(hex($port)[2:].upper().zfill(4))")
    # get the PID of the owner process
    local pid=$(netstat -ntp 2>/dev/null | awk '$6 == "ESTABLISHED" && $5 == "'$addr:$port'"{sub("/.*", "", $7); print $7}')
    [ -z "$pid" ] && { echo 'Address does not match' 2>&1; return 1; }
    # get the inode of the socket
    local inode=$(awk '$4 == "01" && $3 == "'$hex_addr:$hex_port'" {print $10}' /proc/net/tcp)
    [ -z "$inode" ] && { echo 'Cannot lookup the socket' 2>&1; return 1; }
    # query the inode status change time
    local timestamp=$(find /proc/$pid/fd -lname "socket:\[$inode\]" -printf %T@)
    [ -z "$timestamp" ] && { echo 'Cannot fetch the timestamp' 2>&1; return 1; }
    # compute the time difference
    LANG=C printf '%s (%.2fs ago)\n' "$(date -d @$timestamp)" $(bc <<<"$(date +%s.%N) - $timestamp")
}

(करने के लिए धन्यवाद संपादित एलेक्स के लिए फिक्स )

उदाहरण:

$ suptime 93.184.216.34 80
Thu Dec 24 16:22:58 CET 2015 (46.12s ago)

1
यह नुस्खा उस प्रक्रिया की आयु प्रदर्शित करता है जिसने टीसीपी कनेक्शन बनाया था, स्वयं कनेक्शन नहीं।
मायरोस्लाव

@myroslav क्या आप सुनिश्चित हैं? यह इस Node.js स्क्रिप्ट के खिलाफ काम करता है ।
cYrus

मैंने Fedora 22 64-बिट पर अपने फ़ायरफ़ॉक्स द्वारा खोले गए TCP कनेक्शन के साथ आपकी नई स्क्रिप्ट का परीक्षण किया था, और मुझे निश्चित रूप से "अपटाइम" नंबर नहीं मिल रहे हैं। जब नया सॉकेट खुलता है, तो यह "रैंडम" अपटाइम हो रहा है, आमतौर पर "सबसे कम उम्र का" इस्टैब्लिश्ड सॉकेट।
मायरोस्लाव

@myroslav मैं यहां डेबियन (3.16.0-4-amd64) का उपयोग कर रहा हूं, केवल एक चीज जो मैंने नोटिस की है कि रिपोर्ट किया गया समय वास्तव में सॉकेट निर्माण के संबंध में 3 सेकंड देर से है। हो सकता है इसमें कुछ सिस्टम-डिपेंडेंट बिहेवियर शामिल हों ...
cyrus

स्क्रिप्ट के लिए, "$ suptime 192: 168: 120: 10 6379 Traceback (सबसे हालिया कॉल अंतिम): फ़ाइल" <string> ", पंक्ति 1, में <मॉड्यूल> socket.error: अवैध आईपी एड्रेस स्ट्रिंग inet_aton एड्रेस को पास करता है। मैच नहीं "
Ondra kaižka

4

यह प्रश्न मेरे लिए मददगार था, लेकिन मैंने पाया कि मुझे HEX के सभी सामान से बचने के lsofबजाय इसका उपयोग करना चाहिए netstat:

${APP}उपयोगकर्ता द्वारा चलाई जाने वाली प्रक्रिया के लिए ${USER}, निम्नलिखित सभी खुले सॉकेट्स को IP पते $ {IP} पर लौटाता है:

PEEID=$(sudo pgrep -u ${USER} ${APP}) && for i in `sudo lsof -anP -i -u logstash | grep ${IP} | awk '{print $6}'` ; do echo "${device} time" ; sudo find /proc/${PEEID}/fd -lname "socket:\[${device}\]" -printf %t 2> /dev/null  ; echo  ;  done

lsofशामिल PIDभी है, लेकिन मुझे यकीन है कि नहीं यह और डिवाइस संख्या कैसे प्राप्त करने के लिए कर रहा हूँ।

यह अमेज़ॅन लिनक्स पर परीक्षण किया गया था।


3

CYrus द्वारा स्क्रिप्ट ने मेरे लिए काम किया लेकिन मुझे इसे थोड़ा ठीक करना था (हेक्स पते में "L" से छुटकारा पाने के लिए और पोर्ट को 4 अंकों का हेक्स बनाने के लिए):

--- suptime.orig    2015-08-20 15:46:12.896652464 +0200
+++ suptime 2015-08-20 15:47:48.560074728 +0200
@@ -7,8 +7,8 @@
     hex_addr=$(python -c "
 import socket, struct;
 print hex(struct.unpack('<L',
-socket.inet_aton('$addr'))[0])[2:].upper().zfill(8)")
-    hex_port=$(python -c "print hex($port)[2:].upper()")
+socket.inet_aton('$addr'))[0])[2:10].upper().zfill(8)")
+    hex_port=$(python -c "print hex($port)[2:].upper().zfill(4)")
     inode=$(awk '$3 == "'$hex_addr:$hex_port'" {print $10}' /proc/net/tcp)
     time=$(find /proc/$pid/fd -lname "socket:\[$inode\]" -printf %A@)
     LANG=C printf '%.2fs' $(bc <<<"$(date +%s.%N) - $time")

1

कैसा रहेगा:

lsof -t -i @ 192.168.2.110 | xargs ps -fp

आप "ps" कमांड को सिर्फ pid पाने के लिए और -o जैसे समय के साथ शुरू करने के लिए भी कर सकते हैं:

lsof -t -i @ 192.168.2.110 | xargs ps --no-headers -o'pid, start '-p

बेशक यह मानता है कि प्रक्रिया शुरू होने पर सॉकेट शुरू किया गया था।


यह दिखाता है कि सॉकेट को खोलने वाली प्रक्रिया कितनी देर तक है। मामले में एक प्रक्रिया है जो हर समय चलती है और नेटवर्क डिस्कनेक्ट होते हैं, ये मान बहुत भिन्न होंगे। प्रयास के लिए +1
hidralisk

1

CYrus के उत्तर में बनाए रखा स्क्रिप्ट के लिए धन्यवाद। मेरे पास इसे डुप्लिकेट प्रिंट करने के मुद्दे थे, शायद इसलिए कि प्रदान किए गए पते पर विभिन्न पीआईडी ​​से कई कनेक्शन हो सकते हैं, इसलिए यहां मेरा बेहतर संस्करण है जो प्रत्येक आउटपुट लाइन पर पीआईडी ​​प्रिंट करता है:

function suptime() {
    local addr=${1:?Specify the remote IPv4 address}
    local port=${2:?Specify the remote port number}

    # convert the provided address to hex format
    local hex_addr=$(python -c "import socket, struct; print(hex(struct.unpack('<L', socket.inet_aton('$addr'))[0])[2:10].upper().zfill(8))")
    local hex_port=$(python -c "print(hex($port)[2:].upper().zfill(4))")

    # get the inode of the socket
    local inodes=$(awk '$4 == "01" && $3 == "'$hex_addr:$hex_port'" {print $10}' /proc/net/tcp)
    [ -z "$inodes" ] && { echo 'Cannot lookup the socket(s)' 2>&1; return 1; }

    # get file descriptors
    for inode in $inodes; do
        # get inode's file descriptor details
        local fdinfo=( $(find /proc/[0-9]*/fd -lname "socket:\[$inode\]" -printf "%p %T@") )
        [ -z "$fdinfo" ] && { echo 'Cannot find file descriptor' 2>&1; return 1; }

        # extract pid
        local fdpath=${fdinfo[0]}
        local pid=${fdpath#/proc/}
        pid=${pid%%/*}

        # extract timestamp
        local timestamp=${fdinfo[1]}

        # compute the time difference
        LANG=C printf 'PID: %s; Age: %s (%.2fs ago)\n' "$pid" "$(date -d @$timestamp)" $(bc <<<"$(date +%s.%N) - $timestamp")
    done
}

टिप्पणियाँ:

  • जरूरतें bc, netstat( net-toolsrhel> = 7 और इसी तरह की प्रणालियों द्वारा प्रदान की गई )
  • जड़ के रूप में चलाने की जरूरत है
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.