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.
CodePudding user response:
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
CodePudding user response:
In your code, there can also be a ]
before 80 which is not matched by the character class.
The last part for the capture group matches too much \"(. )\"
as the .
can cross matching double quotes.
tcp.*[0-9*\]]:80[[:blank:]] .*[[:blank:]] users:\(\(\"([^"] )\"\,
See a regex demo
For example
#!/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"
You might also 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 thenusers:
\(\("
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