Miha Jamsek
Miha Jamsek

Reputation: 1273

Filter netstat output to get specific ports in bash

I am using command sudo netstat -tulpn to get a list of all opened ports on my computer running Ubuntu Server 16.0.4

This is the output:

user@myServer:~/Skripte$ sudo netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:110             0.0.0.0:*               LISTEN      1319/dovecot
tcp        0      0 0.0.0.0:143             0.0.0.0:*               LISTEN      1319/dovecot
tcp        0      0 192.168.1.22:53         0.0.0.0:*               LISTEN      1147/named
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      1147/named
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1167/sshd
tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN      2644/postgres
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN      1902/master
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN      1147/named
tcp6       0      0 :::9090                 :::*                    LISTEN      951/java
tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      1203/java
tcp6       0      0 :::9001                 :::*                    LISTEN      948/java
tcp6       0      0 :::8009                 :::*                    LISTEN      1203/java
tcp6       0      0 :::3306                 :::*                    LISTEN      1289/mysqld
tcp6       0      0 :::110                  :::*                    LISTEN      1319/dovecot
tcp6       0      0 :::143                  :::*                    LISTEN      1319/dovecot
tcp6       0      0 :::8080                 :::*                    LISTEN      1203/java
tcp6       0      0 :::80                   :::*                    LISTEN      1717/apache2
tcp6       0      0 :::8083                 :::*                    LISTEN      950/java
tcp6       0      0 :::53                   :::*                    LISTEN      1147/named
tcp6       0      0 :::22                   :::*                    LISTEN      1167/sshd
tcp6       0      0 :::5432                 :::*                    LISTEN      2644/postgres
tcp6       0      0 :::25                   :::*                    LISTEN      1902/master
tcp6       0      0 ::1:953                 :::*                    LISTEN      1147/named
tcp6       0      0 :::443                  :::*                    LISTEN      1717/apache2
udp        0      0 192.168.1.22:53         0.0.0.0:*                           1147/named
udp        0      0 127.0.0.1:53            0.0.0.0:*                           1147/named
udp        0      0 0.0.0.0:68              0.0.0.0:*                           1066/dhclient
udp6       0      0 :::53                   :::*                                1147/named

Now, I have tried to write script getPorts.sh [optional search argument] which would either print all ports (if no argument provided) or it would print only ports that are used in filter. However, netstat prints out a lot of information I do not need, so I want my script to filter through this text and give just two informations I am interested in: Port and PID/Program name

Basically, I want this behaviour:

user@myServer:~/Skripte$ ./getPorts.sh java
9090 951/java
8005 1203/java
9001 948/java

user@myServer:~/Skripte$ ./getPorts.sh 8080
8080 1203/java

user@myServer:~/Skripte$ ./getPorts.sh
110 1319/dovecot
143 1319/dovecot
53  1147/named
53  1147/named
22  1167/sshd
5432    2644/postgres
25  1902/master
953 1147/named
9090    951/java
8005    1203/java
9001    948/java
8009    1203/java
3306    1289/mysqld
110 1319/dovecot
143 1319/dovecot
8080    1203/java
80  1717/apache2
8083    950/java
53  1147/named
22  1167/sshd
5432    2644/postgres
25  1902/master
953 1147/named
443 1717/apache2
53  1147/named
53  1147/named
068 1066/dhclient
53  1147/named

I have wrote the following script:

#/bin/bash
filter=${1:-""}
zacasna=$(sudo netstat -tulpn | tr -s ' ' | cut -d ' ' -f 4,6,7 | tr ' ' '\t' | column -t | grep "$filter")
echo "$zacasna"

This script is close to what I am trying to do, however it prints State column, which I do not want (because of those last lines that lack some informations) and also it prints data in quite crude state.

I was looking into using awk for this, but I can't properly use it to achieve this.

Upvotes: 2

Views: 3204

Answers (2)

Darby_Crash
Darby_Crash

Reputation: 446

Another simple solution

#!/bin/bash
[ "$1" ] && filter="^${1}"
sudo netstat -tulpn | grep -oP ':\K(\d+)(?=\s+)|\d+/.*$' | paste -d'\t' - - | grep "$filter"

If you run it with the first argument, the filter search only for ports (from the begin of the line), without first argument it show all informations.

grep search for the port and for the data to the end of the line and after paste merge two lines to time using a tab as separator for a better and clean output.

Some example

$ bash script
5939    863/teamviewerd     
631     25428/cupsd         
4505    950/python          
4506    956/python          
9050    704/tor             
631     25428/cupsd         
53835   539/avahi-daemon: r
5353    539/avahi-daemon: r 
68      20609/dhclient      
631     25430/cups-browsed  
5353    539/avahi-daemon: r 
38675   539/avahi-daemon: r 
$

$ bash script 6
631     25428/cupsd         
631     25428/cupsd         
68      20609/dhclient      
631     25430/cups-browsed  
$

$ bash script 63
631     25428/cupsd         
631     25428/cupsd         
631     25430/cups-browsed  
$

Upvotes: 0

randomir
randomir

Reputation: 18687

Since netstat has fixed column widths, the simplest solution is to use cut -cN-M, e.g:

#/bin/bash
filter=${1:-""}
netstat -tulpn | cut -c21-44,81- | grep "$filter"

An alternative could be to split tcp from udp, and use different column numbers for each. With awk, you could do it like:

netstat -tulpn | awk -vOFS='\t' '/^tcp/{print $4,$7} /^udp/{print $4,$6}' | grep "$filter"

To eliminate grep:

netstat -tulpn | awk -vq="$filter" -vOFS='\t' '$0!~q{next} /^tcp/{print $4,$7} /^udp/{print $4,$6}'

Upvotes: 1

Related Questions