Determine the process pid listening on a certain port
As the title says, I’m running multiple game servers, and every of them has the same name but different PID and the port number. I would like to match the PID of the server which is listening on certain port, and then I would like to kill this process. I need that in order to complete my bash script. Is that even possible? Because it didn’t find yet any solutions on the web.
8 Answers 8
Short version which you can pass to kill command:
This also includes processes that are connected on that port. lsof -i4TCP:80 -sTCP:LISTEN -t is probably what you want, instead.
Exactly what I was looking for. I wanted to kill a process by searching for the port it is running at.
@Nevir what do you mean by » also includes processes that are connected on that port»? Can you please explain?
The -p flag of netstat gives you PID of the process:
*use sudo if showing — instead of PID
Edit: The command that is needed to get PIDs of socket users in FreeBSD is sockstat . As we worked out during the discussion with @Cyclone, the line that does the job is:
sockstat -4 -l | grep :80 | awk '' | head -1
netstat: 80: unknown or uninstrumented protocol used the 80 (nginx) port for testing purpoes. Not worked.
netstat -p -l | grep $PORT and lsof -i :$PORT solutions are good but I prefer fuser $PORT/tcp extension syntax to POSIX (which work for coreutils ) as with pipe:
it prints pure pid so you can drop sed magic out.
One thing that makes fuser my lover tools is ability to send signal to that process directly (this syntax is also extension to POSIX):
$ fuser -k $port/tcp # with SIGKILL $ fuser -k -15 $port/tcp # with SIGTERM $ fuser -k -TERM $port/tcp # with SIGTERM
Finding the PID of the Process Using a Specific Port
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
1. Overview
We all know that a port can only be used by a single application or service at the same time. Sometimes we need to know which process is listening on a specific port.
In this tutorial, we’ll see different approaches to finding the process listening on a particular port in Linux.
2. root Permission
In Linux, only the root user or the process owner can obtain the detailed information of the process.
When we want to check a process listening on a particular port, we don’t know who the process belongs to.
With root permission, we can gain all the necessary information on the process, for instance, the process identifier.
Therefore, we may need to start our network tools with the root user (or with sudo).
3. Using netstat
The netstat command is a member of the net-tools package.
In the past, it came preinstalled in many Linux distributions. However, the net-tools package hasn’t been updated since 2011.
Due to its lack of the support of modern Linux kernel features and other reasons, the net-tools package has become obsolete.
That said, netstat itself is still widely used, so let’s take a look at how it can help.
First of all, let’s see an example output of the netstat command:
root# netstat -ltnup Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:17600 0.0.0.0:* LISTEN 1293/dropbox tcp 0 0 127.0.0.1:17603 0.0.0.0:* LISTEN 1293/dropbox tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 575/sshd tcp 0 0 127.0.0.1:9393 0.0.0.0:* LISTEN 900/perl tcp 0 0 . 80 . * LISTEN 9583/docker-proxy tcp 0 0 . 443 . * LISTEN 9571/docker-proxy udp 0 0 0.0.0.0:68 0.0.0.0:* 8822/dhcpcd .
With the options ltnup, netstat shows us all ports in use in the above example.
Let’s have a look at what the options mean:
- l – show only listening sockets
- t – show TCP connections
- n – show addresses in a numerical form
- u – show UDP connections
- p – show process id/program name
If we review the above output, the last column is exactly what we’re looking for: the PID and Process name listening on a particular port.
We can simply pipe the netstat output to the grep command to get the process information on an individual port.
For example, let’s see which process is listening on port 22:
root# netstat -ltnup | grep ':22' tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 575/sshd
4. Using ss
In the previous section, we discussed that the net-tools package is deprecated.
The ss command is the replacement of the netstat command.
Now let’s see how to use the ss command to see which process is listening on port 22:
root# ss -ltnup 'sport = :22' Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:("sshd",pid=575,fd=3))
If we check the options, we find that the options we passed to the ss command are the same as we passed to netstat.
The only difference is that we were making use of the state-filter of the ss utility instead of an extra grep process to filter the output.
Similar to the output of the netstat command, the expected process information lies in the last column, too.
5. Using lsof
The lsof command can list all open files in a Linux system.
We can use the lsof command to find the process using a specific port with the -i :port_number option:
root# lsof -i :22 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 575 root 3u IPv4 19373 0t0 TCP *:ssh (LISTEN)
The first four columns in the above output tell us the process name listening on port 22 and its PID, owner, and the file descriptor.
We can pass multiple -i :port to the lsof command to find out the processes listening on various ports:
root# lsof -i :22 -i :68 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 575 root 3u IPv4 19373 0t0 TCP *:ssh (LISTEN) dhcpcd 8822 root 10u IPv4 49601 0t0 UDP *:bootpc
6. Using fuser
The fuser utility displays which processes are using named files, sockets, or file systems. It’s included in the psmisc package and preinstalled on many modern Linux distributions by default.
We can use this to view the information of the process running on a specific port. Again let’s find out the PID of the processing listening TCP port 22:
root# fuser 22/tcp 22/tcp: 575
The above output is pretty straightforward. We know that the process with PID 575 is listening on TCP port 22.
However, it doesn’t tell us detailed information about the process, for example, what’s the name of process 575? who owns the process? and so on.
If we want to obtain more details about the process, we can pass the “-v” option to the fuser command to have a verbose output:
root# fuser -v 22/tcp USER PID ACCESS COMMAND 22/tcp: root 575 F. sshd
Using the fuser command, we can also check the running process information on multiple TCP or UDP ports in one shot:
root# fuser -v 22/tcp 68/udp USER PID ACCESS COMMAND 22/tcp: root 575 F. sshd 68/udp: root 8822 F. dhcpcd
7. Conclusion
In this short article, we’ve learned four different Linux command-line utilities with examples to figure out the information of the process listening on a particular port.
They are all very powerful tools to have in our arsenal on the Linux command line.
How to find ports opened by process ID in Linux?
Hmm..I don’t seem to have the —all and —program options. I’m using OSX. Brew doesn’t seem to have a formula for it either.
-n will dramatically speed things up by not resolving hostnames. netsta -tupan is a good default command all and easy to remember.
You can use the command below:
As a side note, netstat -ao will read the /proc/PID/tcp etc to see the ports opened by the process. This means that its reading information supplied by the system (the linux KERNEL), and is in no way directly looking on the network interface or other means. Same goes for lsof.
If you are doing this as a security measure, you failed. You should never (NEVER EVER) trust the output of netstat, even if you are 100% sure you are in fact running a real netstat program (as opposed to a trojaned version) or any other program that reads the /proc filesystem. Some people seem to think that netstat, ls, ps or any other of the standard unix tools do some sort of magic and poll information from the sources, the truth is all of them rely on the /proc filesystem to get all of their data, which can be easily subverted by a rootkit or hypervisor.
If you’re dealing with a rootkitted system or a compromised hypervisor, you can’t trust anything, including something that purports to look directly at the network interface.
You can use the netstat command line tool with the -p command line argument:
-p (Linux):
Process: Show which processes are using which sockets (similar to -b under Windows). You must be root to do this.
To display all ports open by a process with id $PID :
In some embedded devices or with old version of Linux, the problem is netstat do not have —process or -p options available.
The following script shows process with its IP and port, you must be root.
#!/bin/bash for protocol in tcp udp ; do #echo "protocol $protocol" ; for ipportinode in `cat /proc/net/$ | awk '/.*:.*:.*/'` ; do #echo "#ipportinode=$ipportinode" inode=`echo "$ipportinode" | cut -d"|" -f3` ; if [ "#$inode" = "#" ] ; then continue ; fi lspid=`ls -l /proc/*/fd/* 2>/dev/null | grep "socket:\[$inode\]" 2>/dev/null` ; pid=`echo "lspid=$lspid" | awk 'BEGIN /socket/'` ; if [ "#$pid" = "#" ] ; then continue ; fi exefile=`ls -l /proc/$pid/exe | awk 'BEGIN ">/->/'` #echo "$protocol|$pid|$ipportinode" echo "$protocol|$pid|$ipportinode|$exefile" | awk ' BEGIN function iphex2dec(ipport) < ret=sprintf("%d.%d.%d.%d: %d","0x"substr(ipport,1,2),"0x"substr(ipport,3,2), "0x"substr(ipport,5,2),"0x"substr(ipport,7,2),"0x"substr(ipport,10,4)) ; if( ret == "0.0.0.0:0" ) #compatibility others awk versions < ret= strtonum("0x"substr(ipport,1,2)) ; ret=ret "." strtonum("0x"substr(ipport,3,2)) ; ret=ret "." strtonum("0x"substr(ipport,5,2)) ; ret=ret "." strtonum("0x"substr(ipport,7,2)) ; ret=ret ":" strtonum("0x"substr(ipport,10)) ; >return ret ; > < print $1" pid:"$2" local="iphex2dec($3)" remote="iphex2dec($4)" inode:"$5" exe=" $6 ; >' ; #ls -l /proc/$pid/exe ; done ; done
tcp pid:1454 local=1.0.0.127:5939 remote=0.0.0.0:0 inode:13955 exe=/opt/teamviewer/tv_bin/teamviewerd tcp pid:1468 local=1.1.0.127:53 remote=0.0.0.0:0 inode:12757 exe=/usr/sbin/dnsmasq tcp pid:1292 local=0.0.0.0:22 remote=0.0.0.0:0 inode:12599 exe=/usr/sbin/sshd tcp pid:4361 local=1.0.0.127:631 remote=0.0.0.0:0 inode:30576 exe=/usr/sbin/cupsd tcp pid:1375 local=1.0.0.127:5432 remote=0.0.0.0:0 inode:12650 exe=/usr/lib/postgresql/9.3/bin/postgres
With ls you can know the process route.
The fuser command says that the process is: 2054
I’ve added IPv6 support and made a few fixes. Additionally on my system the octets of the IP address are reversed. Dependencies are only to posix shell, awk and cut.
My Version can be found on Github
#!/bin/sh # prints all open ports from /proc/net/* # # for pretty output (if available) start with # ./linux-get-programm-to-port.sh | column -t -s $'\t' #set -x ip4hex2dec () < local ip4_1octet="0x$" local ip4_2octet="$" ip4_2octet="0x$" local ip4_3octet="$" ip4_3octet="0x$" local ip4_4octet="$" ip4_4octet="0x$" local ip4_port="0x$" # if not used inverse #printf "%d.%d.%d.%d:%d" "$ip4_1octet" "$ip4_2octet" "$ip4_3octet" "$ip4_4octet" "$ip4_port" printf "%d.%d.%d.%d:%d" "$ip4_4octet" "$ip4_3octet" "$ip4_2octet" "$ip4_1octet" "$ip4_port" > # reoder bytes, byte4 is byte1 byte2 is byte3 . reorderByte() < if [ $-ne 8 ]; then echo "missuse of function reorderByte"; exit; fi local byte1="$" local byte2="$" byte2="$" local byte3="$" byte3="$" local byte4="$" echo "$byte4$byte3:$byte2$byte1" > # on normal intel platform the byte order of the ipv6 address in /proc/net/*6 has to be reordered. ip6hex2dec()< local ip_str="$" local ip6_port="0x$" local ipv6="$(reorderByte $)" local shiftmask="$" ipv6="$ipv6:$(reorderByte $)" shiftmask="$" ipv6="$ipv6:$(reorderByte $)" ipv6="$ipv6:$(reorderByte $)" ipv6=$(echo $ipv6 | awk '< gsub(/(:0|^0)/, ":"); sub(/(:0)+:/, "::");print>') printf "%s:%d" "$ipv6" "$ip6_port" > for protocol in tcp tcp6 udp udp6 raw raw6; do #echo "protocol $protocol" ; for ipportinode in `cat /proc/net/$protocol | awk '/.*:.*:.*/'` ; do #echo "#ipportinode=$ipportinode" inode=$ if [ "#$inode" = "#" ] ; then continue ; fi lspid=`ls -l /proc/*/fd/* 2>/dev/null | grep "socket:\[$inode\]" 2>/dev/null` ; pids=`echo "$lspid" | awk 'BEGIN /socket/ END>'` ; # removes duplicats for this pid #echo "#lspid:$lspid #pids:$pids" for pid in $pids; do if [ "#$pid" = "#" ] ; then continue ; fi exefile=`ls -l /proc/$pid/exe | awk 'BEGIN ">/->/'`; cmdline=`cat /proc/$pid/cmdline` local_adr_hex=$ remote_adr_hex=$ remote_adr_hex=$ if [ "#$" = "#6" ]; then local_adr=$(ip6hex2dec $local_adr_hex) remote_adr=$(ip6hex2dec $remote_adr_hex) else local_adr=$(ip4hex2dec $local_adr_hex) remote_adr=$(ip4hex2dec $remote_adr_hex) fi echo "$protocol pid:$pid \t$local_adr \t$remote_adr \tinode:$inode \t$exefile $cmdline" done done done