You can try the following:
1. get the PID (say $pid) of the program by adding the -p option to netstat.
2. identify the proper line in the /proc/net/tcp file by looking at the local_address and/or rem_address fields (note that they are in hex format, specifically the IP address is expressed in little-endian byte order), also make sure that the st is 01 (for ESTABLISHED);
3. note the associated inode field (say $inode);
4. search for that inode among the file descriptors in /proc/$pid/fd and finally query the file access time of the symbolic link: 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")
}
#the function used to convert ip between hex and decimal style
ip_cvt() {
local addr=${1:?Please specify <ip:port> or <ip> <port> as the args}
if [ $# -eq 2 ]; then
addr=$1:$2
fi
local ip=${addr%%:*}
local port=${addr##*:}
if [ "$ip" == "${ip##*.}" ]; then
echo $(python -c "import socket, struct; print(socket.inet_ntoa(struct.pack('<L', int('$ip',16))))"):$(printf "%d\n" "0x"$port)
else
echo $(python -c "import socket, struct; print(hex(struct.unpack('<L', socket.inet_aton('$ip'))[0])[2:10].upper().zfill(8))"):$(python -c "print(hex($port)[2:].upper().zfill(4))")
fi
}
$ head /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
the meaning of st field is:
0 /* (Invalid) */ TCP_CLOSE,
1 /* TCP_ESTABLISHED */ TCP_FIN_WAIT1 | TCP_ACTION_FIN,
2 /* TCP_SYN_SENT */ TCP_CLOSE,
3 /* TCP_SYN_RECV */ TCP_FIN_WAIT1 | TCP_ACTION_FIN,
4 /* TCP_FIN_WAIT1 */ TCP_FIN_WAIT1,
5 /* TCP_FIN_WAIT2 */ TCP_FIN_WAIT2,
6 /* TCP_TIME_WAIT */ TCP_CLOSE,
7 /* TCP_CLOSE */ TCP_CLOSE,
8 /* TCP_CLOSE_WAIT */ TCP_LAST_ACK | TCP_ACTION_FIN,
9 /* TCP_LAST_ACK */ TCP_LAST_ACK,
A /* TCP_LISTEN */ TCP_CLOSE,
B /* TCP_CLOSING */ TCP_CLOSING,