Linux'ta soket bağlantı kurma süresi nasıl belirlenir


24

Bağlantının kurulduğunu doğrulayabilirim:

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

Bu tcp bağlantı noktası bağlantısının ne kadar süredir (bağlı) olduğunu kontrol etmenin bir yolu var mı?

(Hayır, uygulama günlüklerine erişimim yok)

Yanıtlar:


23

Aşağıdakileri deneyebilirsiniz:

  1. seçeneğini $pidekleyerek programın PID'sini (diyelim ) alın .-pnetstat

  2. düzgün bir çizgi belirlemek /proc/net/tcpbakarak dosyanın local_addressve / veya rem_addressayrıca emin olun (bunlar özellikle IP adresi little-endian bayt sırayla ifade edilir, altıgen biçiminde olduğunu unutmayın) alanlar stolduğu 01için ( ESTABLISHED);

  3. ilişkili inodealanı not edin (diyelim $inode);

  4. inodedosya tanımlayıcıları arasında arama yapın /proc/$pid/fdve son olarak sembolik bağlantının dosya erişim süresini sorgulayın:

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

Bu bir homurdanma işi ... İşte yukarıdaki noktaları otomatikleştirmek için bir komut dosyası (saplama), uzak adres gerektirir ve soket çalışma süresini saniyeler içinde yazdırır :

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")
}

(Düzenle teşekkür Alex için düzeltmeler )

Misal:

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

1
Bu tarif, bağlantının kendisini değil, TCP bağlantısı oluşturan işlemin yaşını görüntüler.
myroslav

@myroslav emin misin? Bu Node.js komut dosyasına karşı çalışır .
cYrus

Yeni betiğinizi Fedora 22 64-bit üzerinde Firefox tarafından açılan TCP bağlantıları ile test etmiştim ve kesinlikle "çalışma süresi" sayıları almıyorum. Yeni soket açıldığında "rasgele" çalışma süresi, genellikle "en genç" KURULAN soketin zamanı.
myroslav

@myroslav Burada Debian (3.16.0-4-amd64) kullanıyorum, fark ettiğim tek şey bildirilen zamanın soket oluşturma ile ilgili olarak yaklaşık 3 saniye geç olmasıdır. Belki bazı sisteme bağlı davranışlar vardır ...
cYrus

Komut dosyası için, "$ suptime 192: 168: 120: 10 6379 Geri izleme (en son çağrı sonuncusu): <module> socket.error dosyasında" <string> ", satır 1 dosyası: inet_aton adresine geçersiz IP adresi dizesi geçiyor maç yok "
Ondra 24ižka

4

Bu sorular benim için yararlı oldu, ancak tüm HEX şeylerinden kaçınmama izin vermek lsofyerine kullanarak buldum netstat:

${APP}Kullanıcı tarafından çalıştırılan bir işlem ${USER}için aşağıdakiler tüm açık yuvaları $ {IP} IP adresine döndürür:

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

Çok lsofiçerir PID, ancak nasıl ve cihaz numarası almak için emin değilim.

Bu Amazon Linux'ta test edildi.


3

CYrus tarafından komut dosyası benim için çalıştı ama biraz düzeltmek zorunda kaldı (hex adresinde bir "L" kurtulmak ve bağlantı noktası 4 haneli bir hex yapmak için):

--- 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

Nasıl olur:

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

Ayrıca "ps" komutunu sadece -o ile pid ve başlangıç ​​zamanı alacak şekilde uyarlayabilirsiniz:

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

Elbette bu, soketin işlem sırasında başlatıldığını varsayar.


bu, soketi açan işlemin ne kadar sürdüğünü gösterir. Sürekli çalışan bir işlem olması ve ağ bağlantılarının kesilmesi durumunda, bu değerler çok farklı olacaktır. Çaba için +1
hidralisk

1

CYrus'un cevabında tutulan senaryo için teşekkürler. Muhtemelen farklı PID'lerden sağlanan adrese birçok bağlantı olabileceğinden, çoğaltmaları yazdırmayla ilgili sorunlar yaşadım, bu yüzden her çıkış satırında PID'yi de yazdıran gelişmiş sürümüm:

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
}

Notlar:

  • ihtiyaçları bc, netstat( net-toolsrhel> = 7 ve benzeri sistemler tarafından sağlanır)
  • root olarak çalıştırılması gerekiyor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.