I want to use bash to grep if any process is listening on port 80,but now I stumble upon other port number which annoys me. How can I filter this in grep?
netstat -ant|grep LISTEN|grep 80|wc -l
It also outputs other records such as 8080 8088 and so on.
I'm looking at the output of my netstat
command, and see this:
tcp4 0 0 10.0.1.10.56941 64.34.119.101.80 ESTABLISHED
tcp4 0 0 10.0.1.10.56936 64.34.119.101.80 ESTABLISHED
tcp4 0 0 10.0.1.10.56932 64.34.119.101.80 ESTABLISHED
tcp4 0 0 10.0.1.10.56929 64.34.119.101.80 ESTABLISHED
tcp4 0 0 10.0.1.10.56922 64.34.119.101.80 ESTABLISHED
tcp4 0 0 10.0.1.10.56914 64.34.119.101.80 ESTABLISHED
tcp4 0 0 *.* *.* CLOSED
tcp46 0 0 *.80 *.* LISTEN
tcp4 0 0 127.0.0.1.49153 *.* LISTEN
tcp4 0 0 127.0.0.1.49152 *.* LISTEN
tcp4 0 0 *.631 *.* LISTEN
tcp6 0 0 *.631 *.* LISTEN
I take it that the port is the last number in the five part dotted output. That means that
grep "\.80 "
will pick up only port 80. The \.
says to pick up the period. (Normally the period means any character in regular expressions). And, by putting a space after the 80
, you'll guarantee that you're not going to pick up port 8080. In fact, you're guaranteed that you're not going to pick up IP addresses that have .80
in them.
In fact, I'd recommend to use awk
instead of grep
. With awk
, you can specify fields and do a bit more processing:
$ netstat -ant | awk '$6 == "LISTEN" && $4 ~ /\.80$/' | wc -l
With awk
each column automatically becomes a separate field. Field #6 ($6 in awk) is the one that says ESTABLISHED
, CLOSED
, LISTEN
in it. Field $4
is the first column IP address one.
In the above, I'm looking for lines that have the word LISTEN in the sixth field, and where field #4 matches the regular expression \.80$
. The $
is an anchor to the end of the string, and the \.
is picking up a decimal point and not representing any character. The awk
command automatically prints out each line that matches, so I don't have to specify that.
Awk is really a programming language. It assumes a read loop for each line in the file. You can have a BEGIN
clause that gets executed before the file is read and an END
clause that executes after the file has been read. The various fields are numbered and represented with a dollar sign. The special $0
variable represents the whole line. Special variables like like NF gives you the number of fields in a line and NR gives you the number of lines read in. You also have a whole slew of functions to help parse text, etc. Here's a full blown version of the awk
script that basically lays out everything for you, and does its own line counting, so you don't have to pipe to wc -l
.:
$ netstat -ant | awk '
BEGIN {total = 0}
END {print "There are " total " lines I found"}
{
if ($6 == "LISTEN" && $4 ~ /\.80$/) {
total = total + 1
}
}'
OP gets the following output:
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN
In this case, try either:
$ netstat -ant | awk '$6 == "LISTEN" && $4 ~ /:80$/' | wc -l
Where the \.
is replaced by a :
or...
$ netstat -ant | awk '$6 == "LISTEN" && $4 ~ /[\.:]80$/' | wc -l
Which uses [\.:]
which will get it whether it's a colon or a period. Heck, might as well go all the way...
$ netstat -ant | awk '$6 == "LISTEN" && $4 ~ /[^0-9]80$/' | wc -l
The [^0-9]
means not a numeric character. You can't go wrong with that. This way, whether it's a period, a colon, a semi-colon, a comma, or whatever separator your version of netstat
uses, it will work.
Instead of grepping the output of netstat
-- asking for more information than you need and then discarding the bulk of it -- simply ask fuser
which process has the port you care about open:
$ fuser -n tcp 4005
4005/tcp: 19339
If you only care to know if any process has the port in question open, you can do this even more quickly and efficiently, without needing to process output at all, by using the -q
argument to fuser and operating on its exit status:
if fuser -q -n tcp 4005 ; then
echo "port is in use"
else
echo "port not in use"
fi
If you want to know how many connections there are to a remote port, fuser can do that too:
fuser -n tcp ,,80
...or connections to a remote port on a specific host:
fuser -n tcp ,1.2.3.4,80
In short -- using the right tool for the job to query for the parameters you want directly prevents you from needing to do text-based filtering in the first place.
Use grep ":80 "
instead of grep 80
You can take advantage of the fact that ports are preceded by a colon (like :80
). The fasting thing then would be something like:
netstat -ant | grep ':80\b.*LISTEN'
That way you're not invoking grep
twice. Also, grep has the ability to count matches with -c
, so you can use that instead of wc
:
netstat -ant | grep -c ':80\b.*LISTEN'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With