3

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?

asked Sep 19, 2011 at 14:12
3
  • 3
    You can use grep -q instead of sending stdout to /dev/null. Commented Sep 19, 2011 at 16:05
  • Comment you've marked as approved answer is flawed — 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 Commented Apr 14, 2012 at 16:33
  • I don't agree that there is such flaw (see comments). But JodieC's answer does look better, just as Gilles' one. Commented Apr 15, 2012 at 4:04

5 Answers 5

3

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
    
answered Sep 19, 2011 at 21:31
10
  • 1
    I advice not using grep, when there's no need in regexps fgrep fits better. Commented Apr 13, 2012 at 4:48
  • 1
    @poige But here you do have a regexp. And using fgrep (or rather grep -F, since fgrep 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 with fgrep - and it would need to use pipe, just as in the OP's example. Commented 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. :) Commented Apr 14, 2012 at 16:27
  • 3
    2) 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 your grep actually has that spec. symbs. — dots. That's a flaw, actually. Commented Apr 14, 2012 at 16:27
  • 2
    Not only at the beginning, there's a port as well where, say :80 would match ":80anything" — that's why I support solution using ss. And yeah, when there's terminator like :, dots can be safe. But otherwise 192.168.1.4 perfectly matches the whole 192.168.104, for e. g.. Commented Apr 15, 2012 at 4:27
2

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"]
 }
'
answered Sep 19, 2011 at 22:55
2

with ss:

if ss -n -o state established '( dport = $hostname:$portnumber )'|awk 'NR==2{exit 0}END{exit 1}';then 
answered Apr 13, 2012 at 4:05
1

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.

answered Sep 19, 2011 at 15:41
1

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.

answered Sep 19, 2011 at 17:43

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.