Как получить только PID, без какой-либо дополнительной информации, процесса, выполняющегося на порте 3000?

18

Я использую CentOS 7. Я хочу получить PID (если он существует) процесса, работающего на порте 3000. Я хотел бы получить этот 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 сам по себе без всей этой дополнительной информации.

Дейв
источник
sudo ss -lptnH "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g', Вам нужно объяснение?
user996142
2
Никаких объяснений не требуется, но это приводит к ошибке "ss: invalid option - 'H'".
Дейв,
У вас наверняка есть старый ssбез этой опции. Должно работать даже без него:sudo ss -lptn "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g'
user996142
2
@ user996142 не очень полезный комментарий. может быть хороший ответ, хотя
ааааа говорит восстановить Монику

Ответы:

33

Другое возможное решение:

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
Юрий Гончарук
источник
Попробовал "lsof -t -i: 3000 TCP: LISTEN" и получил ошибку: "lsof: ошибка состояния на TCP: LISTEN: нет такого файла или каталога"
Дейв
@ Дэйв Запустите это без TCP:LISTEN.
Сюн Чямов
2
@ Дэйв, я пропустил -sключ. Я исправил это в шаблоне. Пример имел этот ключ.
Юрий Гончарук
Правильный инструмент для работы.
Йоханнес Кун
10

Попробуй это:

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

(требуется psmiscпакет)

Обратите внимание, что это надежно только при запуске пользователем root. Другой пользователь может только надеяться найти процессы, запущенные с тем же пользователем.


Скучное объяснение только для root-доступа с примером здесь.
Какой бы метод ни использовался (fuser, ss, lsof, ...), все они в конечном итоге сопоставляют доступный список дескрипторов процесса с доступным списком сетевых подключений (например, для tcp, в котором он доступен /proc/net/tcp).
Например, попытка получить pid с использованием порта 22/tcp(с 22 = 0x0016) в конечном итоге приведет к такому сравнению:

Вход от /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.

AB
источник
4

В то время как 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

Поэтому, если вы хотите использовать идентификатор группы процессов вместо PID, вы можете сделать:

$ sudo lsof -F g -i :22 -s TCP:LISTEN | awk '/^g/{print substr($0, 2)}'
901
Мур
источник
2

Это то что нужно именно

sudo lsof -n -i :3000  | awk '/LISTEN/{print $2}'
12726
12730
12732
Arushix
источник
1

Предостережение: я могу проверить это только на 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мы просто используем « / » от netstatвыхода «s ПИД / программы в качестве разделителя.

Роберт Ридл
источник