It seems lsof is a bit too heavy on the system when multiple
healthchecks are running in parallel.
So instead of calling a "big" process, let's split a bit things and get
to the filesystem directly in order to pick only the things we actually
need.
What changes:
- using /proc/net/{tcp,udp}, we get every socket matching the port
- using find with the right options, we can ensure at least one socket
exists with the wanted inode(s)
The last part exits as soon as we have a match in order to make it
faster and less resource consuming.
Change-Id: I64776992a7e457781aa8ddaba359ef085d4cb77d
Partial-Bug: #1921714
(cherry picked from commit a072a7f07e)
# First convert port to hex value. We need to 0-pad it in order to get the
# right format (4 chars).
for p in $@;do
ports="${ports}|$(printf'%0.4x'$p)"
done
# Format the string - will be ":(hex1|hex2|...)"
ports=":(${ports:1})"
# Parse the files. We need to extract only one value (socket inode) based on the matching port. Let's check local and target for establised connection.
# Using the main /proc/net/{tcp,udp} allow to take only the connections existing in the current container. If we were using /proc/PID/net/{tcp,udp}, we
# would get all the connections existing in the same network namespace as the PID. Since we're using network=host, that would show *everything*.
# the "join" method is weird, and fails if the array is empty.
# Note: join comes from gawk's /usr/share/awk/join.awk and has some weird parameters.
sockets=$(awk -i join -v m=${ports}'{IGNORECASE=1; if ($2 ~ m || $3 ~ m) {output[counter++] = $10} } END{if (length(output)>0) {print join(output, 0, length(output)-1, "|")}}' /proc/net/{tcp,udp})
# If no socket, just fail early
test -z $sockets&&exit1
match=0
for pid in $(pgrep -f $process);do
# Here, we check if a socket is actually associated to the process PIDs