obtenha o PID (digamos $pid) do programa adicionando a -popção a netstat.
identifique a linha correta no /proc/net/tcparquivo observando os campos local_addresse / ou rem_address(observe que eles estão no formato hexadecimal, especificamente o endereço IP é expresso na ordem de bytes little-endian), e também verifique se o sté 01(para ESTABLISHED);
observe o inodecampo associado (digamos $inode);
procure isso inodeentre os descritores de arquivo /proc/$pid/fde, finalmente, consulte o tempo de acesso ao arquivo do link simbólico:
Isso é um trabalho árduo ... aqui está um script (stub) para automatizar os pontos acima, requer o endereço remoto e imprime o tempo de atividade do soquete em segundos:
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")
}
Esta receita exibe a idade do processo que criou a conexão TCP, não a própria conexão.
Myroslav
@myroslav você tem certeza? Ele funciona contra esse roteiro Node.js .
Cyrus
Eu testei seu novo script com conexões TCP abertas pelo meu Firefox no Fedora 22 de 64 bits, e definitivamente não estou recebendo números de "tempo de atividade". Quando um novo soquete é aberto, ele está recebendo um tempo de atividade "aleatório", geralmente o tempo do soquete "mais jovem" ESTABELECIDO.
Myroslav
@myroslav Estou usando o Debian (3.16.0-4-amd64) aqui, a única coisa que noto é que o tempo relatado está realmente 3 segundos atrasado em relação à criação do soquete. Talvez existam alguns comportamentos dependentes do sistema envolvidos ...
Cyrus
Para o script, "$ suptime 192: 168: 120: 10 6379 Traceback (última chamada mais recente): arquivo" <string> ", linha 1, em <module> socket.error: string de endereço IP ilegal passada para inet_aton não corresponde "
Ondra Žižka 24/11
4
Essas perguntas foram úteis para mim, mas eu achei que usar, em lsofvez de netstatme deixar evitar todo o material HEX:
Para um processo ${APP}executado pelo usuário ${USER}, o seguinte retorna todos os soquetes abertos para o endereço IP $ {IP}:
O script do cYrus funcionou para mim, mas eu tive que corrigi-lo um pouco (para me livrar de um "L" no endereço hexadecimal e para tornar a porta num hexadecimal de 4 dígitos):
isso mostra quanto tempo o processo que abriu o soquete permanece. Caso exista um processo que seja executado o tempo todo e haja desconexões de rede, esses valores seriam muito diferentes. +1 para esforço
hidralisk 26/06
1
Obrigado pelo script mantido na resposta do cYrus. Eu tive problemas com a impressão de duplicatas, provavelmente porque pode haver muitas conexões de PIDs diferentes para o endereço fornecido, então aqui está minha versão aprimorada que também imprime o PID em cada linha de saída:
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
}
Notas:
necessidades bc, netstat(fornecido por net-toolssobre rhel> = 7 e sistemas semelhantes)
Essas perguntas foram úteis para mim, mas eu achei que usar, em
lsof
vez denetstat
me deixar evitar todo o material HEX:Para um processo
${APP}
executado pelo usuário${USER}
, o seguinte retorna todos os soquetes abertos para o endereço IP $ {IP}:O
lsof
contémPID
também, mas não sei como obtê-lo e o número do dispositivo.Isso foi testado no Amazon Linux.
fonte
O script do cYrus funcionou para mim, mas eu tive que corrigi-lo um pouco (para me livrar de um "L" no endereço hexadecimal e para tornar a porta num hexadecimal de 4 dígitos):
fonte
E se:
Você também pode personalizar o comando "ps" para obter apenas pid e iniciar a hora com -o, como:
Obviamente, isso pressupõe que o soquete foi iniciado quando o processo foi iniciado.
fonte
Obrigado pelo script mantido na resposta do cYrus. Eu tive problemas com a impressão de duplicatas, provavelmente porque pode haver muitas conexões de PIDs diferentes para o endereço fornecido, então aqui está minha versão aprimorada que também imprime o PID em cada linha de saída:
Notas:
bc
,netstat
(fornecido pornet-tools
sobre rhel> = 7 e sistemas semelhantes)fonte