0

I've found this way of checking whether a host is accessible on a given port, however I am only interested in the status code of the command, therefore I am trying something like this:

[CptBartender@somewhere ~]$ <dev/tcp/host/port ; echo $?
0

This works fine if I try on an open port, however if I check a closed port, I get:

[CptBartender@somewhere ~]$ <dev/tcp/host/blocked_port ; echo $?
-bash: connect: Connection refused
-bash: /dev/tcp/host/blocked_port: Connection refused
1

Now my next step was to try and discard the outputs of the first command, so I tried:

[CptBartender@somewhere ~]$ <dev/tcp/host/blocked_port >/dev/null/ 2>&1; echo $?
-bash: connect: Connection refused
-bash: /dev/tcp/host/blocked_port: Connection refused
1

Same output. My questions are, why is the first command printin any output whatsoever and how do I prevent it from doing so?

CptBartender
  • 125
  • 1
  • 6

1 Answers1

2

It's not the command that's printing output. You don't have any command – the < /dev/tcp/… is just regular input redirection and is processed by the shell itself.

(And not just that, but redirections are processed left-to-right, so the < redirection is processed before the 2>&1 one, so it couldn't be redirected anyway.)

You can get around this by running the "command" in a subshell. For example:

( </dev/tcp/$host/$port ) 2>/dev/null

Actually it seems that in this case a subshell isn't required; a command group will work even if it's within the same process – it still forces the "outer" redirections to be processed first:

{ </dev/tcp/$host/$port; } 2>/dev/null

Side note: /dev/tcp is a magic path that's handled by bash itself – it doesn't actually exist in Linux's /dev, but can be used with bash redirections. However, this trick won't work with #!/bin/sh, and there's still a chance that it won't work with bash on some older systems (which used to disable this feature), or some non-Linux systems.

grawity
  • 501,077