Currently I'm using netstat for this:
if netstat -an | grep ESTABLISHED | grep $address:$port > /dev/null; then
# command
fi
Is there a more elegant solution?
5 Answers 5
As far as elegance is concerned, I'd modify two things in your command:
- As mentioned in comment by Chris, you can use
-q
instead of output redirection. Use one
grep
instead of two:if netstat -an | grep -q " $address:$port .* ESTABLISHED"; then
-
1I advice not using
grep
, when there's no need in regexpsfgrep
fits better.poige– poige2012年04月13日 04:48:26 +00:00Commented Apr 13, 2012 at 4:48 -
1@poige But here you do have a regexp. And using
fgrep
(or rathergrep -F
, sincefgrep
is deprecated) in this case is useless also due to negligible potential speed benefit in a single invocation. It would take far more time to type a (longer) working filter withfgrep
- and it would need to use pipe, just as in the OP's example.rozcietrzewiacz– rozcietrzewiacz2012年04月13日 06:40:10 +00:00Commented Apr 13, 2012 at 6:40 -
My bad, I've overlooked it. Regarding fgrep: 1) GNU's man can call it deprecated (whatever), but neither does BSD's or Solaris'. So I don't care typing extra
-f
to grep, neither advice doing that to anyone. :)poige– poige2012年04月14日 16:27:04 +00:00Commented Apr 14, 2012 at 16:27 -
32) Lots of people tend blindly use
grep
and spending theirs time in escaping its spec. symbols, or what's a way worse, getting wrong results having forgotten to escape such symbs.. Look,$address
you've used in yourgrep
actually has that spec. symbs. — dots. That's a flaw, actually.poige– poige2012年04月14日 16:27:32 +00:00Commented Apr 14, 2012 at 16:27 -
2Not only at the beginning, there's a port as well where, say
:80
would match ":80anything" — that's why I support solution usingss
. And yeah, when there's terminator like:
, dots can be safe. But otherwise192.168.1.4
perfectly matches the whole 192.168.104, for e. g..poige– poige2012年04月15日 04:27:42 +00:00Commented Apr 15, 2012 at 4:27
lsof
should do the job. Ask it to give you machine-parseable output with the -F
option.
lsof -n -i @${hostname}:${port} -F nT | grep '^TST=ESTABLISHED$'
If you need more information:
lsof -n -i -F nT | awk '
function host_port(s, a) {
match(s, /:[^:]*$/);
a["host"] = substr(s, 1, RSTART-1);
a["port"] = substr(s, RSTART+1);
}
sub(/^p/,"") {pid = 0ドル}
sub(/^n/,"") {
split(0,ドル endpoints, "->");
host_port(endpoints[1], from);
host_port(endpoints[2], to);
}
/^TST=ESTABLISHED$/ {
print "Established from", from["host"] ":" from["port"],
"to", to["host"] ":" to["port"]
}
'
with ss
:
if ss -n -o state established '( dport = $hostname:$portnumber )'|awk 'NR==2{exit 0}END{exit 1}';then
That works well enough for now, for Linux.
On other UNIX systems (the ones I have my hands on are Mac OS X and Solaris) the port is separated by .
instead of :
.
And this will most likely fail for any IPv6 connection. netstat
truncates IPv6 addresses, so make sure to use --wide
. But again, that's not a portable option.
You can use lsof
instead of netstat
: something like this: sudo /usr/sbin/lsof -i [email protected]:80
, but lsof is only available for root user and often not installed by default, so it's additional external dependency.
grep -q
instead of sending stdout to /dev/null.grep
and IP-addresses are pitfall, since usual notation for IP-addresses has dots inside. See my comments: unix.stackexchange.com/questions/21020/… P. S. I'd mark as answer this one: unix.stackexchange.com/a/36354/6622