Reputation: 1273
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
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
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