我正在使用 CentOS 7。我想获取在端口 3000 上运行的进程的 PID(如果存在)。我想获取此 PID 以便将其保存到 shell 脚本中的变量中。到目前为止我已经
[rails@server proddir]$ sudo ss -lptn 'sport = :3000'
State Recv-Q Send-Q Local Address:Port Peer Address:Port
Cannot open netlink socket: Protocol not supported
LISTEN 0 0 *:3000 *:* users:(("ruby",pid=4861,fd=7),("ruby",pid=4857,fd=7),("ruby",pid=4855,fd=7),("ruby",pid=4851,fd=7),("ruby",pid=4843,fd=7))
但如果没有这些额外的信息,我无法弄清楚如何单独隔离 PID。
答案1
另一种可能的解决方案:
lsof -t -i :<port> -s <PROTO>:LISTEN
例如:
# lsof -i :22 -s TCP:LISTEN
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1392 root 3u IPv4 19944 0t0 TCP *:ssh (LISTEN)
sshd 1392 root 4u IPv6 19946 0t0 TCP *:ssh (LISTEN)
# lsof -t -i :22 -s TCP:LISTEN
1392
答案2
尝试这个:
pid=$(fuser 3000/tcp 2>/dev/null)
(需要psmisc
包)
请注意,这仅在由 root 用户运行时才可靠。其他用户只能希望找到以同一用户运行的进程。
对于仅 root 访问的无聊解释,请参见此处的示例。
无论使用什么方法(fuser、ss、lsof...),它们最终都会将可用的进程描述符列表与可用的网络连接列表相匹配(例如,对于 tcp,它在 中可用/proc/net/tcp
)。
例如,尝试使用端口22/tcp
(22 = 0x0016)获取 pid 最终会进行这种比较:
条目来自/proc/net/tcp
:
0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 141408 1 000000000a9ac1b5 100 0 0 10 0
和:
dr-x------. 2 root root 0 May 14 17:59 /proc/358/fd lrwx------. 1 root root 64 May 14 17:59 /proc/358/fd/3 -> socket:[141408]
由于此 fd 描述符仅对其用户(在本例中恰好是 root)或 root 可用,因此只有该用户或 root 才能找到 pid 为 358。
答案3
虽然lsof
s-t
是获取 PID 的最简单方法,lsof
但也可以使用以下选项选择其他字段-F
:
$ lsof -F'?'
lsof: ID field description
a access: r = read; w = write; u = read/write
c command name
d device character code
D major/minor device number as 0x<hex>
f file descriptor (always selected)
G file flaGs
i inode number
k link count
K task ID (TID)
l lock: r/R = read; w/W = write; u = read/write
L login name
m marker between repeated output
n comment, name, Internet addresses
o file offset as 0t<dec> or 0x<hex>
p process ID (PID)
g process group ID (PGID)
P protocol name
r raw device number as 0x<hex>
R paRent PID
s file size
S stream module and device names
t file type
T TCP/TPI info
u user ID (UID)
0 (zero) use NUL field terminator instead of NL
输出如下(请注意,始终打印 PID 和文件描述符):
$ sudo lsof -F cg -i :22 -s TCP:LISTEN
p901
g901
csshd
f3
f4
因此,如果您想要进程组 ID 而不是 PID,您可以这样做:
$ sudo lsof -F g -i :22 -s TCP:LISTEN | awk '/^g/{print substr($0, 2)}'
901
答案4
警告:我只能在 RedHat 上进行测试。
应该可以与netstat
?
sudo netstat -npl --inet | awk '/:3000/' | awk -F "[ /]+" '{print $7}'
-n对于数字端口
-l用于监听端口
-p查看 PID
您可以使用--inet或者--inet6开关告诉netstat
分别只查找 IPv4 或 IPv6,否则您可能会得到两个结果。
或者你可以告诉awk
只打印一次
sudo netstat -npl | awk '/:3000/' | awk -F "[ /]+" '{print $7; exit}'
我们awk
只使用 '/' from netstat
PID/程序的输出作为分隔符。