Cách xác định thời gian kết nối ổ cắm trên Linux


24

Tôi có thể xác minh rằng kết nối đã hết:

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

Có cách nào để kiểm tra kết nối cổng tcp này (kết nối) được bao lâu không?

(Không, tôi không có quyền truy cập vào nhật ký ứng dụng)

Câu trả lời:


23

Bạn có thể thử như sau:

  1. lấy PID (nói $pid) của chương trình bằng cách thêm -ptùy chọn vào netstat.

  2. xác định dòng thích hợp trong /proc/net/tcptệp bằng cách xem các trường local_addressvà / hoặc rem_address(lưu ý rằng chúng có định dạng hex, cụ thể là địa chỉ IP được thể hiện theo thứ tự byte cuối nhỏ), cũng đảm bảo rằng đó st01(for ESTABLISHED);

  3. lưu ý trường liên quan inode(nói $inode);

  4. tìm kiếm inodetrong số các mô tả tệp trong /proc/$pid/fdvà cuối cùng truy vấn thời gian truy cập tệp của liên kết tượng trưng:

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

Đó là một công việc khó khăn ... đây là một kịch bản (còn sơ khai) để tự động hóa các điểm trên, nó yêu cầu địa chỉ từ xa và nó in thời gian hoạt động của ổ cắm trong vài giây:

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

(Chỉnh sửa nhờ Alex cho sửa chữa )

Thí dụ:

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

1
Công thức này hiển thị tuổi của quá trình tạo kết nối TCP, chứ không phải kết nối.
myroslav

@myroslav bạn có chắc không? Nó hoạt động chống lại tập lệnh Node.js này .
cYrus

Tôi đã kiểm tra tập lệnh mới của bạn với các kết nối TCP được mở bởi Firefox của tôi trên Fedora 22 64 bit và tôi chắc chắn không nhận được số "thời gian hoạt động". Khi ổ cắm mới mở, nó sẽ nhận được thời gian hoạt động "ngẫu nhiên", thường là thời gian của ổ cắm được thành lập "trẻ nhất".
myroslav

@myroslav Tôi đang sử dụng Debian (3.16.0-4-amd64) ở đây, điều duy nhất tôi nhận thấy là thời gian được báo cáo thực sự trễ khoảng 3 giây đối với việc tạo ổ cắm. Có thể có một số hành vi phụ thuộc vào hệ thống có liên quan ...
cYrus

Đối với tập lệnh, "$ suptime 192: 168: 120: 10 6379 TracBack (cuộc gọi gần đây nhất): Tệp" <chuỗi> ", dòng 1, trong <module> socket.error: chuỗi địa chỉ IP bất hợp pháp được chuyển đến inet_aton Địa chỉ không phù hợp "
Ondra ižka

4

Câu hỏi này hữu ích với tôi, nhưng tôi thấy sử dụng lsofthay vì netstatđể tôi tránh tất cả những thứ HEX:

Đối với một quá trình được ${APP}chạy bởi người dùng ${USER}, sau đây trả về tất cả các ổ cắm mở cho địa chỉ 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

Nó cũng lsofchứa PID, nhưng tôi không chắc làm thế nào để lấy nó và số thiết bị.

Điều này đã được thử nghiệm trên Amazon Linux.


3

Kịch bản của cYrus đã làm việc cho tôi nhưng tôi đã phải sửa nó một chút (để loại bỏ chữ "L" trong địa chỉ hex và để tạo cổng thành hex gồm 4 chữ số):

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

Làm thế nào về:

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

Bạn cũng có thể điều chỉnh lệnh "ps" để lấy pid và bắt đầu thời gian với -o như:

lsof -t -i @ 192.168.2.110 | xargs ps --no-headers -o'pid, bắt đầu '-p

Tất nhiên điều này giả định rằng ổ cắm đã được bắt đầu khi quá trình này.


Điều này cho thấy quá trình mở ổ cắm kéo dài bao lâu. Trong trường hợp có một quá trình chạy mọi lúc và có sự ngắt kết nối mạng, các giá trị này sẽ rất khác nhau. +1 cho nỗ lực
hidralisk

1

Cảm ơn vì kịch bản được duy trì trong câu trả lời của cYrus. Tôi gặp vấn đề với việc in các bản sao, có thể là do có thể có nhiều kết nối từ các PID khác nhau đến địa chỉ được cung cấp, vì vậy đây là phiên bản cải tiến của tôi cũng in ra PID trên mỗi dòng đầu ra:

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
}

Ghi chú:

  • nhu cầu bc, netstat(được cung cấp bởi net-toolstrên rrc> = 7 và các hệ thống tương tự)
  • cần phải được chạy như root
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.