uzyskaj PID (powiedzmy $pid) programu, dodając -popcję do netstat.
zidentyfikuj właściwą linię w /proc/net/tcppliku, patrząc na pola local_addressi / lub rem_address(zauważ, że są one w formacie szesnastkowym, w szczególności adres IP jest wyrażony w kolejności bajtów little-endian), upewnij się również, że stjest 01(dla ESTABLISHED);
zanotuj powiązane inodepole (powiedzmy $inode);
wyszukaj to inodewśród deskryptorów plików /proc/$pid/fdi na koniec sprawdź czas dostępu do pliku łącza symbolicznego:
To cholerna robota ... oto skrypt (skrót) do automatyzacji powyższych punktów, wymaga zdalnego adresu i wypisuje czas działania gniazda w kilka sekund:
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")
}
Ten przepis wyświetla wiek procesu, który utworzył połączenie TCP, a nie samo połączenie.
myroslav
@myroslav jesteś pewien? To działa przeciwko tym skrypcie node.js .
cYrus
Przetestowałem twój nowy skrypt z połączeniami TCP otwartymi przez mojego Firefoksa na Fedorze 22 64-bit, i zdecydowanie nie dostaję numerów „przestojów”. Kiedy nowe gniazdo się otwiera, robi się „losowe” uptime, zwykle czas „najmłodszego” ESTABLISHED gniazda.
myroslav,
@myroslav Używam tutaj Debiana (3.16.0-4-amd64), jedyne, co zauważam, to fakt, że zgłaszany czas jest tak naprawdę około 3 sekund opóźniony w odniesieniu do utworzenia gniazda. Może w
grę
W przypadku skryptu „$ suptime 192: 168: 120: 10 6379 Traceback (ostatnie ostatnie wywołanie): Plik„ <ciąg>> wiersz 1 w <module> socket.error: niedozwolony ciąg adresu IP przekazany do adresu inet_aton not match "
Ondra Žižka
4
Te pytania były dla mnie pomocne, ale znalazłem używanie lsofzamiast netstatpozwalania mi unikać wszystkich rzeczy HEX:
W przypadku procesu ${APP}uruchamianego przez użytkownika ${USER}poniższe zwraca wszystkie otwarte gniazda na adres IP $ {IP}:
Skrypt autorstwa cYrus zadziałał dla mnie, ale musiałem go trochę naprawić (aby pozbyć się „L” w adresie szesnastkowym i uczynić port 4-cyfrowym szesnastkowym):
pokazuje to, jak długo trwa proces, który otworzył gniazdo. W przypadku ciągłego procesu i rozłączenia sieci wartości te byłyby bardzo różne. +1 za wysiłek
hidralisk
1
Dzięki za skrypt utrzymany w odpowiedzi cYrus. Miałem problemy z drukowaniem duplikatów, prawdopodobnie dlatego, że może istnieć wiele połączeń z różnych PID do podanego adresu, więc oto moja ulepszona wersja, która drukuje również PID na każdej linii wyjściowej:
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
}
Uwagi:
potrzeby bc, netstat(pod warunkiem, przez net-toolsna RHEL> = 7 i podobnych układów)
Te pytania były dla mnie pomocne, ale znalazłem używanie
lsof
zamiastnetstat
pozwalania mi unikać wszystkich rzeczy HEX:W przypadku procesu
${APP}
uruchamianego przez użytkownika${USER}
poniższe zwraca wszystkie otwarte gniazda na adres IP $ {IP}:lsof
ZawieraPID
też, ale nie jestem pewien, jak je zdobyć i numer urządzenia.Zostało to przetestowane na Amazon Linux.
źródło
Skrypt autorstwa cYrus zadziałał dla mnie, ale musiałem go trochę naprawić (aby pozbyć się „L” w adresie szesnastkowym i uczynić port 4-cyfrowym szesnastkowym):
źródło
Co powiesz na:
Możesz także dostosować polecenie „ps”, aby po prostu uzyskać pid i rozpocząć czas z -o, na przykład:
Oczywiście zakłada to, że gniazdo zostało uruchomione, gdy proces był.
źródło
Dzięki za skrypt utrzymany w odpowiedzi cYrus. Miałem problemy z drukowaniem duplikatów, prawdopodobnie dlatego, że może istnieć wiele połączeń z różnych PID do podanego adresu, więc oto moja ulepszona wersja, która drukuje również PID na każdej linii wyjściowej:
Uwagi:
bc
,netstat
(pod warunkiem, przeznet-tools
na RHEL> = 7 i podobnych układów)źródło