如何确定 Linux 上的套接字连接时间

hid*_*isk 32 linux sockets

我可以验证连接是否已启动:

$ netstat -tn | grep "192.168.2.110"
tcp  0  0 192.168.2.100:10444  192.168.2.110:52639  ESTABLISHED
Run Code Online (Sandbox Code Playgroud)

有没有办法检查此 tcp 端口连接已启动(已连接)多长时间?

(不,我无权访问应用日志)

cYr*_*rus 30

您可以尝试以下操作:

  1. 得到PID(比如$pid通过加入该计划的)-p选项netstat

  2. /proc/net/tcp通过查看local_address和/或rem_address字段(请注意它们是十六进制格式,特别是 IP 地址以小端字节顺序表示)来识别文件中的正确行,还要确保stis 01(for ESTABLISHED);

  3. 注意相关的inode字段(比如$inode);

  4. 搜索是inode在文件描述符中/proc/$pid/fd终于查询符号链接的文件访问时间:

    find /proc/$pid/fd -lname "socket:\[$inode\]" -printf %t
    
    Run Code Online (Sandbox Code Playgroud)

这是一项艰巨的工作......这是一个自动化上述要点的脚本(存根),它需要远程地址并以秒为单位打印套接字正常运行时间:

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")
}
Run Code Online (Sandbox Code Playgroud)

(编辑感谢亚历克斯修复

例子:

$ suptime 93.184.216.34 80
Thu Dec 24 16:22:58 CET 2015 (46.12s ago)
Run Code Online (Sandbox Code Playgroud)

  • 此配方显示创建 TCP 连接的进程的年龄,而不是连接本身。 (2认同)
  • 这可以工作,但不准确:创建套接字本身时不会创建“/proc/$pid/fd/$fd”条目,而是仅在第一次创建此“/proc/$pid/fd”目录时创建列出(在 Linux 5.4.0 上测试)。如果您希望它准确,您必须定期列出该目录。 (2认同)

小智 6

这个问题对我很有帮助,但我发现使用lsof而不是netstat让我避免所有十六进制的东西:

${APP}对于user 运行的进程${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
Run Code Online (Sandbox Code Playgroud)

lsof包含PID,但我不知道如何获取它和设备编号。

这是在 Amazon Linux 上测试的。