22

I would like to use netcat to send a piece of text to the echo service on my server, get the reply then exit, so that I know the connection is still good. so far I've tried:

 echo 'test' | netcat server 7 

this way netcat would wait for more input rather than exit.

How can I make netcat exit after getting reply from the echo service?

SparedWhisle
  • 3,668

12 Answers12

17

Just tried - slightly different behaviour between netcat-openbsd and netcat-traditional ( ubuntu 16.4). The OpenBSD variant does what you expect, while with the netcat-traditional I need to add the -q 1 to avoid waiting for more input.

echo 'test' | netcat -q 1 server 7
jhilmer
  • 554
13

I know this is a bit old but no other answer worked for me and this did:

echo 'test' | netcat -N $server $port

Notice the -N:

shutdown the network socket after EOF on the input. Some servers require this to finish their work.

Worked for me on both Windows and Linux.

8

Use this:

cat <(echo command) - | nc host port

The problem is that nc will close the connection immediately after stdin is closed, which is very quick for a simple my_command string, and thus never gets the chance to receive a response. If you pipe a very large file you will see that it might get a response before it's done sending the file.

Enter cat with - as second argument: it makes cat listen on stdin for more content to pipe through after it has sent the contents of the first argument. The first argument is just getting the echo command through cat – it could also be a file with your commands a la cat < file - | ....

The downside of that is now that it stays open until you hit ^C or ^D on the shell. Adding a timeout using -w 1 (OSX netcat) or -i 1 (nmap's ncat) makes it close the connection after 1 second, but it won't exit the process until you enter some character.

This answer is based on this answer to an identical superuser question.

  • 1
    cat <(echo command) <(sleep 1) | nc host port causes stdin to stay open as long as the sleep command runs without the need to set nc timeouts or have the user "enter some character". – romanows Jan 19 '20 at 21:27
6

Your command should work. It is very similar to some of the examples in the netcat manpage.

This is exactly how netcat is supposed to operate: once it has reached EOF on stdin, it (one-way) closes the connection /to/ the server and then waits for data coming from the server. When the latter closes the connection (the other way: server->client), then netcat stops.

If your netcat command doesn't finish, I suppose there is something strange happening at the network level that keeps the echo server listening for additional input.

You can try out the -q option to force netcat to stop N seconds after EOF is encountered on stdin:

netcat -q1 server echo <<< "test"

(<<< "test" is a bashism, use your echo ... | syntax if you don't use bash)

xhienne
  • 17,793
  • 2
  • 53
  • 69
3

I don't understand your question properly?

The default netcat listener should exit upon receiving input (in this case your echo pipes it to netcat which forwards it to the listener).

If you want the listening Netcat service to stay listening after it receives input:

nc -lk 12345
  • where 12345 is the port number

Most importantly though, please check the man pages for netcat.. they are amazingly useful for all commands...

man nc
2

I'd recommend socat instead:

echo test | socat -t 10 - tcp:server:7

(here waiting for up to 10 seconds for the server to reply and shutdown)

socat can do much much much more than the various (different and incompatible) implementations of nc/netcat, and generally works more reliably. It's your ultimate plumbing Swiss Army knife.

Quoting the man page for the -t option:

-t<timeout>
When one channel has reached EOF, the write part of the other channel is shut down. Then, socat waits [timeval] seconds before terminating. Default is 0.5 seconds. This timeout only applies to addresses where write and read part can be closed independently. When during the timeout interval the read part gives EOF, socat terminates without awaiting the timeout.

So above, after echo writes test\n, it exits, which closes the pipe. socat sees EOF on its - channel (stdin), then shuts the writing direction of the TCP socket and waits for the remote service to shutdown as well or for 10 seconds of inactivity whichever comes first. The echo service is meant to terminate the connection as soon as the other end has shut down its sending direction, so that command should not take any longer than the time it takes to establish the connection, exchanging the data and shutting down.

With OpenBSD's netcat or its port to Linux which is the default one on recent versions of Debian and derivatives at least, an approximation would be nc -Nw10 server 7 (that's different in that nc's -w is both a connection timeout and an inactivity timeout)

To implement a TCP echo service on port 7777 for testing:

socat tcp-listen:7777,reuseaddr,fork exec:cat,nofork

(the fork to fork a process for each incoming connection, nofork to execute cat directly in that process with its stdin/stdout being the TCP socket, like when using (x)inetd).

Some timing on the loopback interface, with zsh:

$ time echo test | socat -t10 - tcp:localhost:7777
test
echo test  0.00s user 0.00s system 54% cpu 0.001 total
socat -t10 - tcp:localhost:7777  0.00s user 0.01s system 55% cpu 0.009 total
0

sending a ping to Redis and grep the PONG:

echo 'PING' | nc -w 1 server 6379 | grep PONG

Works as Ansible command.

OlliO
  • 1
0

Actually, the best way to close gracefully the connection is to send the Content-Length header like following. Client (like curl will close the connection after receiving the data.

DATA="Date: $(date)"; 
LENGTH=$(echo $DATA | wc -c);
echo -e "HTTP/1.1 200 OK\nContent-Length: ${LENGTH}\n\n${DATA}" | nc -l -p 8000;
0

I just check the timeout cmd while trying the nc command, like :

echo "test" | timeout 10 netcat server 7

This waits 10 sec before closing the connection.

bu5hman
  • 4,756
Alexandre
  • 101
0

I realize this is quite old, and already has an accepted answer. However, that answer is very inelegant and doesn't really do what this question is asking for.

What you should be doing is passing the -N flag with your netcat command. The -N flag does the following:

shutdown the network socket after EOF on the input. Some servers require this to finish their work.

So your command would look like this:

 echo 'test' | netcat -N server 7 

Just for reference, passing the -q 1 flag is just telling netcat to quit after 1 second. So that doesn't necessarily mean you'll get the output you want, or that whatever you are attempting will finish whatever it is you are wanting to do.

0

Using busybox netcat, the process of reading a reply and exiting can be achieved by using the -w flag:

nc server 7 -w1

reads some response from server on port 7, waits one second and exits

Unfortunately, the minimum wait time is 1 second. This may or may not be desirable.

smac89
  • 1,443
-1
(echo 'test'; sleep 1) | netcat server 7 

This keeps the input open for some time to delay netcat ending.

Kusalananda
  • 333,661