How to find ports opened by process ID in Linux?

LinuxBashNetworking

Linux Problem Overview


Suppose the PID of the process is already known

Linux Solutions


Solution 1 - Linux

netstat --all --program | grep '3265'
  • --all show listening and non-listening sockets.
  • --program show the PID and name of the program to which socket belongs.

You could also use a port scanner such as Nmap.

Solution 2 - Linux

You can use the command below:

lsof -i -P |grep pid

Solution 3 - Linux

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.

Solution 4 - Linux

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.

The example section gives this example: >To display all ports open by a process with id $PID: > > netstat -ao | grep '\b'$PID'\b'

Solution 5 - Linux

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/${protocol} | awk '/.*:.*:.*/{print $2"|"$3"|"$10 ;}'` ; 
	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{FS="/"} /socket/{print $3}'` ;
    	if [ "#$pid" = "#" ] ; then continue ; fi
	    exefile=`ls -l /proc/$pid/exe | awk 'BEGIN{FS=" -> "}/->/{print $2;}'`
		#echo "$protocol|$pid|$ipportinode" 
    	echo "$protocol|$pid|$ipportinode|$exefile" | awk '
	    	BEGIN{FS="|"}
		    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

The output is like:

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

Solution 6 - Linux

With ls you can know the process route.

Example:

fuser 25/tcp

The fuser command says that the process is: 2054

ls -l /proc/2054/exe

The process path appears

Extracted from: https://www.sysadmit.com/2018/06/linux-que-proceso-usa-un-puerto.html

Image example

Solution 7 - Linux

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${1%???????????}"

    local ip4_2octet="${1%?????????}"
    ip4_2octet="0x${ip4_2octet#??}"

    local ip4_3octet="${1%???????}"
    ip4_3octet="0x${ip4_3octet#????}"

    local ip4_4octet="${1%?????}"
    ip4_4octet="0x${ip4_4octet#??????}"

    local ip4_port="0x${1##*:}"
    
    # 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 [ ${#1} -ne 8 ]; then echo "missuse of function reorderByte"; exit; fi
    
    local byte1="${1%??????}"

    local byte2="${1%????}"
    byte2="${byte2#??}"

    local byte3="${1%??}"
    byte3="${byte3#????}"

    local byte4="${1#??????}"

    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="${1%%:*}"
    local ip6_port="0x${1##*:}"
    local ipv6="$(reorderByte ${ip_str%????????????????????????})"
    local shiftmask="${ip_str%????????????????}"
    ipv6="$ipv6:$(reorderByte ${shiftmask#????????})"
    shiftmask="${ip_str%????????}"
    ipv6="$ipv6:$(reorderByte ${shiftmask#????????????????})"
    ipv6="$ipv6:$(reorderByte ${ip_str#????????????????????????})"
    ipv6=$(echo $ipv6 | awk '{ gsub(/(:0{1,3}|^0{1,3})/, ":"); 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 '/.*:.*:.*/{print $2"|"$3"|"$10 ;}'` ; 
    do 
        #echo "#ipportinode=$ipportinode"
        inode=${ipportinode##*|}
        if [ "#$inode" = "#" ] ; then continue ; fi 

        lspid=`ls -l /proc/*/fd/* 2>/dev/null | grep "socket:\[$inode\]" 2>/dev/null` ; 
        pids=`echo "$lspid" | awk 'BEGIN{FS="/"} /socket/{pids[$3]} END{for (pid in pids) {print pid;}}'` ;  # 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{FS=" -> "}/->/{print $2;}'`;
            cmdline=`cat /proc/$pid/cmdline`
         
            local_adr_hex=${ipportinode%%|*}
            remote_adr_hex=${ipportinode#*|}
            remote_adr_hex=${remote_adr_hex%%|*}

            if [ "#${protocol#???}" = "#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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionomgView Question on Stackoverflow
Solution 1 - LinuxJorge ZuanonView Answer on Stackoverflow
Solution 2 - LinuxWaveterView Answer on Stackoverflow
Solution 3 - LinuxdanielView Answer on Stackoverflow
Solution 4 - LinuxlotharView Answer on Stackoverflow
Solution 5 - LinuxabrusaView Answer on Stackoverflow
Solution 6 - LinuxJimmy OlsenView Answer on Stackoverflow
Solution 7 - LinuxwofView Answer on Stackoverflow