Bagaimana cara saya hanya mendapatkan PID, tanpa informasi tambahan, dari proses yang berjalan pada port 3000?

18

Saya menggunakan CentOS 7. Saya ingin mendapatkan PID (jika ada) dari proses yang berjalan pada port 3000. Saya ingin mendapatkan PID ini untuk keperluan menyimpannya ke variabel dalam skrip shell. Sejauh ini saya punya

[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))

tapi saya tidak tahu bagaimana mengisolasi PID dengan sendirinya tanpa semua informasi tambahan ini.

Dave
sumber
sudo ss -lptnH "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g'. Apakah Anda perlu penjelasan?
user996142
2
Tidak diperlukan penjelasan tetapi ini menghasilkan kesalahan "ss: invalid option - 'H'".
Dave
Anda mungkin memiliki yang lama sstanpa opsi ini. Harus bekerja bahkan tanpa itu:sudo ss -lptn "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g'
user996142
2
@ user996142 bukan komentar yang sangat membantu. mungkin jawaban yang bagus
aaaaa mengatakan mengembalikan Monica

Jawaban:

33

Solusi lain yang mungkin:

lsof -t -i :<port> -s <PROTO>:LISTEN

Sebagai contoh:

# 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
Yurij Goncharuk
sumber
Mencoba "lsof -t -i: 3000 TCP: LISTEN" dan mendapat kesalahan, "lsof: status error pada TCP: LISTEN: Tidak ada file atau direktori"
Dave
@ Jangan Jalankan tanpa TCP:LISTEN.
Xiong Chiamiov
2
@ Sudah saya kehilangan -skunci. Saya sudah memperbaikinya dalam pola. Contoh punya kunci ini.
Yurij Goncharuk
Alat yang tepat untuk pekerjaan itu.
Johannes Kuhn
10

Coba ini:

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

(membutuhkan psmiscpaket)

Harap dicatat, bahwa ini hanya dapat diandalkan ketika dijalankan oleh root pengguna. Pengguna lain hanya bisa berharap menemukan proses yang berjalan dengan pengguna yang sama.


Penjelasan membosankan untuk akses hanya root dengan contoh di sini.
Apa pun metode yang digunakan (fuser, ss, lsof, ...) mereka semua akhirnya cocok dengan daftar deskriptor proses yang tersedia dengan daftar koneksi jaringan yang tersedia (misalnya untuk tcp tersedia di /proc/net/tcp).
Misalnya, mencoba untuk mendapatkan pid menggunakan port 22/tcp(dengan 22 = 0x0016) akan berakhir dengan melakukan perbandingan seperti ini:

Entri dari /proc/net/tcp:
0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 141408 1 000000000a9ac1b5 100 0 0 10 0

dengan:
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]

Karena deskriptor fd ini hanya tersedia untuk penggunanya (yang kebetulan menjadi root dalam contoh ini) atau root, hanya pengguna atau root yang dapat mengetahui pid adalah 358.

AB
sumber
4

Sementara lsofitu -tadalah cara paling sederhana untuk mendapatkan PID, lsofjuga memiliki cara untuk memilih bidang lain menggunakan -Fopsi:

$ 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

Dengan output seperti itu (perhatikan bahwa PID dan deskriptor file selalu dicetak):

$ sudo lsof -F cg -i :22 -s TCP:LISTEN 
p901
g901
csshd
f3
f4

Jadi, jika Anda menginginkan ID grup proses alih-alih PID, Anda bisa melakukan:

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

Inilah yang sebenarnya Anda butuhkan

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

Peringatan: Saya hanya bisa menguji ini di RedHat.

Haruskah mungkin dengan netstat?

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

-n untuk port numerik
-l untuk mendengarkan port
-p untuk melihat PID

Anda dapat menggunakan sakelar --inet atau --inet6 untuk memberi tahu netstatmasing-masing hanya mencari IPv4 atau IPv6, jika tidak, Anda mungkin mendapatkan dua hasil.

Atau Anda dapat meminta awkuntuk mencetak hanya sekali

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

Dalam awkkita hanya menggunakan ' / ' dari netstat'output PID / program sebagai pemisah.

Robert Riedl
sumber