web-dev-qa-db-ja.com

ポート3000で実行されているプロセスのPIDのみを取得し、追加情報はありません。

CentOS 7を使用しています。ポート3000で実行されているプロセスのPID(存在する場合)を取得します。このPIDを取得して、シェルスクリプトの変数に保存します。これまでのところ

[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を単独で分離する方法を理解できません。

18
Dave

別の可能な解決策:

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
33
Yurij Goncharuk

これを試して:

pid=$(fuser 3000/tcp 2>/dev/null)

psmiscパッケージが必要)

これは、ユーザー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であることを確認できます。

10
A.B

lsof-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

したがって、PIDの代わりにプロセスグループIDが必要な場合は、次のようにします。

$ Sudo lsof -F g -i :22 -s TCP:LISTEN | awk '/^g/{print substr($0, 2)}'
901
4
muru

これはあなたが正確に必要なものです

Sudo lsof -n -i :3000  | awk '/LISTEN/{print $2}'
12726
12730
12732
2
Arushix

警告:これはRedHatでのみテストできます

netstatで可能でしょうか?

 Sudo netstat -npl --inet | awk '/:3000/' | awk -F "[ /]+" '{print $7}'

-n数値ポートの場合
-lリスニングポート用
-p PIDを表示する

-inetまたは-inet6スイッチを使用して、netstatは、それぞれIPv4またはIPv6のみを検索します。それ以外の場合、2つの結果が得られることがあります。

または、awkに1回だけ印刷するように指示することもできます

Sudo netstat -npl | awk '/:3000/' | awk -F "[ /]+" '{print $7; exit}' 

awkでは、PID /プログラムのnetstatの出力からの '/'をセパレーターとして使用します。

1
Robert Riedl