dapatkan PID (katakanlah $pid) dari program dengan menambahkan -popsi ke netstat.
mengidentifikasi baris yang tepat dalam /proc/net/tcpfile dengan melihat bidang local_addressdan / atau rem_address(perhatikan bahwa mereka dalam format hex, khususnya alamat IP diekspresikan dalam urutan bit-endian byte), juga pastikan bahwa stis 01(untuk ESTABLISHED);
Itu adalah pekerjaan kasar ... inilah sebuah skrip (rintisan) untuk mengotomatiskan poin-poin di atas, ia membutuhkan alamat jarak jauh dan mencetak uptime soket dalam hitungan detik:
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")
}
Resep ini menampilkan usia proses yang menciptakan koneksi TCP, bukan koneksi itu sendiri.
myroslav
@ myroslav kamu yakin? Ia bekerja melawan skrip Node.js ini .
cYrus
Saya telah menguji skrip baru Anda dengan koneksi TCP yang dibuka oleh Firefox saya di Fedora 22 64-bit, dan saya jelas tidak mendapatkan angka "uptime". Ketika soket baru terbuka, itu menjadi "acak" uptime, biasanya waktu soket ESTABLISHED "termuda".
myroslav
@ myroslav Saya menggunakan Debian (3.16.0-4-amd64) di sini, satu-satunya hal yang saya perhatikan adalah waktu yang dilaporkan sebenarnya terlambat sekitar 3 detik sehubungan dengan pembuatan soket. Mungkin ada beberapa perilaku yang tergantung pada sistem yang terlibat ...
cYrus
Untuk skrip, "$ suptime 192: 168: 120: 10 6379 Traceback (panggilan terakhir terakhir): File" <string> ", baris 1, di <module> socket.error: string alamat IP ilegal yang diteruskan ke inet_aton Address tidak tidak cocok "
Ondra Žižka
4
Pertanyaan-pertanyaan ini sangat membantu saya, tetapi saya menemukan menggunakan lsofdaripada netstatmembiarkan saya menghindari semua hal HEX:
Untuk proses yang ${APP}dijalankan oleh pengguna ${USER}, berikut ini mengembalikan semua soket terbuka ke alamat IP $ {IP}:
Script oleh cYrus bekerja untuk saya tetapi saya harus memperbaikinya sedikit (untuk menghilangkan "L" di alamat hex dan untuk membuat port hex 4 digit):
ini menunjukkan berapa lama proses yang membuka soket sudah habis. Jika ada proses yang berjalan sepanjang waktu dan ada terputusnya jaringan, nilai-nilai ini akan sangat berbeda. +1 untuk upaya
hidralisk
1
Terima kasih atas skrip yang dijaga dalam jawaban cYrus. Saya mempunyai masalah dengan itu mencetak duplikat, mungkin karena mungkin ada banyak koneksi dari PID yang berbeda ke alamat yang disediakan, jadi inilah versi saya yang ditingkatkan yang juga mencetak PID pada setiap jalur keluaran:
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
}
Catatan:
kebutuhan bc, netstat(disediakan oleh net-toolspada rhel> = 7 dan sistem serupa)
Pertanyaan-pertanyaan ini sangat membantu saya, tetapi saya menemukan menggunakan
lsof
daripadanetstat
membiarkan saya menghindari semua hal HEX:Untuk proses yang
${APP}
dijalankan oleh pengguna${USER}
, berikut ini mengembalikan semua soket terbuka ke alamat IP $ {IP}:The
lsof
berisiPID
juga, tapi saya tidak yakin bagaimana untuk mendapatkannya dan jumlah perangkat.Ini diuji di Amazon Linux.
sumber
Script oleh cYrus bekerja untuk saya tetapi saya harus memperbaikinya sedikit (untuk menghilangkan "L" di alamat hex dan untuk membuat port hex 4 digit):
sumber
Bagaimana tentang:
Anda juga dapat menyesuaikan perintah "ps" untuk mendapatkan pid dan memulai waktu dengan -o seperti:
Tentu saja ini mengasumsikan soket sudah dimulai ketika proses itu.
sumber
Terima kasih atas skrip yang dijaga dalam jawaban cYrus. Saya mempunyai masalah dengan itu mencetak duplikat, mungkin karena mungkin ada banyak koneksi dari PID yang berbeda ke alamat yang disediakan, jadi inilah versi saya yang ditingkatkan yang juga mencetak PID pada setiap jalur keluaran:
Catatan:
bc
,netstat
(disediakan olehnet-tools
pada rhel> = 7 dan sistem serupa)sumber