Câu trả lời:
Bạn có thể thử như sau:
lấy PID (nói $pid
) của chương trình bằng cách thêm -p
tùy chọn vào netstat
.
xác định dòng thích hợp trong /proc/net/tcp
tệp bằng cách xem các trường local_address
và / hoặc rem_address
(lưu ý rằng chúng có định dạng hex, cụ thể là địa chỉ IP được thể hiện theo thứ tự byte cuối nhỏ), cũng đảm bảo rằng đó st
là 01
(for ESTABLISHED
);
lưu ý trường liên quan inode
(nói $inode
);
tìm kiếm inode
trong số các mô tả tệp trong /proc/$pid/fd
và cuối cùng truy vấn thời gian truy cập tệp của liên kết tượng trưng:
find /proc/$pid/fd -lname "socket:\[$inode\]" -printf %t
Đó là một công việc khó khăn ... đây là một kịch bản (còn sơ khai) để tự động hóa các điểm trên, nó yêu cầu địa chỉ từ xa và nó in thời gian hoạt động của ổ cắm trong vài giây:
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")
}
(Chỉnh sửa nhờ Alex cho sửa chữa )
Thí dụ:
$ suptime 93.184.216.34 80
Thu Dec 24 16:22:58 CET 2015 (46.12s ago)
Câu hỏi này hữu ích với tôi, nhưng tôi thấy sử dụng lsof
thay vì netstat
để tôi tránh tất cả những thứ HEX:
Đối với một quá trình được ${APP}
chạy bởi người dùng ${USER}
, sau đây trả về tất cả các ổ cắm mở cho địa chỉ 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
Nó cũng lsof
chứa PID
, nhưng tôi không chắc làm thế nào để lấy nó và số thiết bị.
Điều này đã được thử nghiệm trên Amazon Linux.
Kịch bản của cYrus đã làm việc cho tôi nhưng tôi đã phải sửa nó một chút (để loại bỏ chữ "L" trong địa chỉ hex và để tạo cổng thành hex gồm 4 chữ số):
--- suptime.orig 2015-08-20 15:46:12.896652464 +0200
+++ suptime 2015-08-20 15:47:48.560074728 +0200
@@ -7,8 +7,8 @@
hex_addr=$(python -c "
import socket, struct;
print hex(struct.unpack('<L',
-socket.inet_aton('$addr'))[0])[2:].upper().zfill(8)")
- hex_port=$(python -c "print hex($port)[2:].upper()")
+socket.inet_aton('$addr'))[0])[2:10].upper().zfill(8)")
+ hex_port=$(python -c "print hex($port)[2:].upper().zfill(4)")
inode=$(awk '$3 == "'$hex_addr:$hex_port'" {print $10}' /proc/net/tcp)
time=$(find /proc/$pid/fd -lname "socket:\[$inode\]" -printf %A@)
LANG=C printf '%.2fs' $(bc <<<"$(date +%s.%N) - $time")
Làm thế nào về:
lsof -t -i @ 192.168.2.110 | xargs ps -fp
Bạn cũng có thể điều chỉnh lệnh "ps" để lấy pid và bắt đầu thời gian với -o như:
lsof -t -i @ 192.168.2.110 | xargs ps --no-headers -o'pid, bắt đầu '-p
Tất nhiên điều này giả định rằng ổ cắm đã được bắt đầu khi quá trình này.
Cảm ơn vì kịch bản được duy trì trong câu trả lời của cYrus. Tôi gặp vấn đề với việc in các bản sao, có thể là do có thể có nhiều kết nối từ các PID khác nhau đến địa chỉ được cung cấp, vì vậy đây là phiên bản cải tiến của tôi cũng in ra PID trên mỗi dòng đầu ra:
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
}
Ghi chú:
bc
, netstat
(được cung cấp bởi net-tools
trên rrc> = 7 và các hệ thống tương tự)