2

I'm trying to use a bash regex from a ss comand output to extract the name of the application that is using a given port in a function. I have some problems with the regex.

Command to check the data is ss -tupln

Example of data to parse (ipv4):

tcp    LISTEN   0        10                0.0.0.0:80          0.0.0.0:*    users:(("nc",pid=3474,fd=4))          
tcp    LISTEN   0        10                   [::]:80             [::]:*    users:(("nc",pid=3474,fd=3))  

In this case I want to extract nc which is the name of the program using the port

Example of data to parse (ipv6):

tcp   LISTEN 0      511                 *:80              *:*    users:(("apache2",pid=6741,fd=4),("apache2",pid=6740,fd=4),("apache2",pid=6738,fd=4),("apache2",pid=6737,fd=4),("apache2",pid=6736,fd=4),("apache2",pid=6724,fd=4))

In this case I want to extract apache2 which is the name of the program using the port.

I need a general regex valid for both cases. I don't care if it is get using grep or if is done using pure bash regex. My non-working approach:

#!/bin/bash

get_name() {
    local regexp="${1}.*[0-9\*]:${2}[[:blank:]]+.*[[:blank:]]+users:\(\(\"(.+)\"\,"

    [[ $(ss -tupln) =~ ${regexp} ]] && process_name="${BASH_REMATCH[1]}" 

    echo "${process_name}"
}
get_name "tcp" "80"

Thanks.

OscarAkaElvis
  • 5,384
  • 4
  • 27
  • 51

2 Answers2

1

You can use awk like that:

$ ss -tupln | awk -v proto=tcp -v port=80 '$1 == proto && $5 ~ ":" port "$" {split($0, array, "\""); print array[2]}'
apache2
Arkadiusz Drabczyk
  • 11,227
  • 2
  • 25
  • 38
1

You might use gnu grep:

ss -tupln | grep -oP 'tcp\h.*?:80\h.*?\busers:\(\("\K[^"]+(?=")'

The pattern matches:

  • tcp\h Match tcp and a space
  • .*?:80\h Match as least as possible chars and then :80 and a space
  • .*?\busers: Match as least as possible chars and then users:
  • \(\(" match (("
  • \K[^"]+ Forget what is matched to far (it will not be part of the resulting match)
  • (?=") Positive lookahead, assert = directly to the right

See a regex demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70
  • The grep solution worked... the other solution didn't work. Please modify it because I put this as accepted answer to not confuse others. Thanks. – OscarAkaElvis Oct 13 '21 at 09:26
  • @OscarAkaElvis I can remove the first part of the answer if you want, and leave only the gnu grep solution. (I did test the `get_name()` function on ubuntu 20.04 and for me it worked out) – The fourth bird Oct 13 '21 at 09:29