TCP connection, bash only
< and > are usually used to redirect IOs. What does it mean there? Is it usable in another context? How?
It's the same - input and output is redirected to fd 5.
Why does it work, while /dev/tcp doesn't exists?
It's a special file: If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open a TCP connection to the corresponding socket.
Why 5? Can it be another number? What are the values allowed?
Yes, it can be any value, but you need to ensure you don't use an fd already in use.
Why is exec necessary? (given nothing is actually executed)
exec means the redirection happens in the current shell, not within a subshell.
Read and write to the same netcat tcp connection
The correct way to do this in UNIX is to make use of a back pipe. You can do so as follows:
First, create a pipe: mknod bkpipe p
This creates a file named bkpipe
of type pipe.
Next, figure out what you need to do. Here are two useful scenarios. In these, replace the hosts/addresses and port numbers with the appropriate ports for your relay.
To forward data sent to a local port to a remote port on another machine:
nc -l -p 9999 0<bkpipe | nc remotehost 7000 | tee bkpipe
To connect to another machine and then relay data in that connection to another:
nc leftHost 6000 0<bkpipe | nc rightHost 6000 | tee bkpipe
If you simply need to handle basic IPC within a single host, however, you can do away with netcat completely and just use the FIFO pipe that mknod creates. If you stuff things into the FIFO with one process, they will hang out there until something else reads them out.
Bash script to close open TCP connections on a specific port
I'm not familiar with the findstr
command, but there's no need to use another command to search for matching lines, as awk
can do that by itself.
netstat -ano | awk '$1 == "TCP" && $2 ~ /:8080/ { print $5 }'
Connecting to an open port with bash
It depends on the shell; bash
, for instance, uses I/O redirection to attach to arbitrary TCP and UDP sockets. From the man page:
Bash handles several filenames specially when they are used in redirections, as
described in the following table:
[...]
/dev/tcp/host/port
If host is a valid hostname or Internet address, and port is
an integer port number or service name, bash attempts to open a
TCP connection to the corresponding socket.
/dev/udp/host/port
If host is a valid hostname or Internet address, and port is
an integer port number or service name, bash attempts to open a
UDP connection to the corresponding socket.
For example, to get the current time:
cat < /dev/tcp/time-a.nist.gov/13
Note that it must be a redirection; cat /dev/tcp/time-a.nist.gov/13
would only work if your file system implemented some sort of sockets-on-demand.
A very basic HTTP client:
$ exec 3<>/dev/tcp/www.example.com/80
$ echo "GET /" >&3
$ cat <&3
How to decrease TCP connect() system call timeout?
It is determined by TCP. It can be decreased on a per-socket basis by application code.
NB The timeout only takes effect if there is no response at all. If there is a connection refusal, the error occurs immediately.
Persistent connection in Bash script
When a process is started in the background in a script, standard input is redirected from /dev/null
. This means the first cat
command will read and emit EOF
as soon as it executes, which will cause netcat to exit immediately after starting, so the output later in the script will never make it to the fifo, because there isn't an active listener at that time.
In this case, when cat > fifo
is evaluated, the shell forks a child process, redirects standard input from /dev/null
, and attempts to open fifo
for write. The child remains in a blocking open
call at this time. Note that cat
is not executed until after the open
call completes.
Next, cat fifo | nc -v localhost 3000
is spawned. cat
opens fifo
for read, which allows the blocking open
from the first child to complete and the first cat
to execute.
The first cat
inherits its parent's file descriptors, so its standard input is attached to /dev/null
and it thus reads and emits an EOF
immediately. The second cat
reads the EOF
and passes that to the standard input of nc
, which causes netcat to exit.
By the time the echo
statements are evaluated, the processes identified by $pid1
and $pid2
are finished. Since there is no longer a listener on fifo
, the first echo
will block forever.
I don't have a pure-shell fix, but you can use an external program like perl to open the placeholder writer to fifo
instead of using shell redirection. Aside, please note that there is a race with nc
starting after the echo
statements (where the kill
happens before netcat has a chance to process input/send output), so here I added a delay after the cat | nc
expression. There is almost certainly a better solution out there, but here's what I came up with:
#!/bin/bash
rm -f fifo
mkfifo fifo
perl -e 'open(my $fh, ">", "fifo"); sleep 3600 while 1' &
pid1=$!
cat fifo | nc -v localhost 3000 &
pid2=$!
sleep 2
echo sending...
echo comando1 > fifo
echo comando2 > fifo
echo comando3 > fifo
kill -9 $pid1 $pid2
Hope this helps, great question!
Efficiently test if a port is open on Linux?
A surprise I found out recently is that Bash natively supports tcp connections as file descriptors. To use:
exec 6<>/dev/tcp/ip.addr.of.server/445
echo -e "GET / HTTP/1.0\n" >&6
cat <&6
I'm using 6 as the file descriptor because 0,1,2 are stdin, stdout, and stderr. 5 is sometimes used by Bash for child processes, so 3,4,6,7,8, and 9 should be safe.
As per the comment below, to test for listening on a local server in a script:
exec 6<>/dev/tcp/127.0.0.1/445 || echo "No one is listening!"
exec 6>&- # close output connection
exec 6<&- # close input connection
To determine if someone is listening, attempt to connect by loopback. If it fails, then the port is closed or we aren't allowed access. Afterwards, close the connection.
Modify this for your use case, such as sending an email, exiting the script on failure, or starting the required service.
How to listen for multiple tcp connection using nc
Simultaneous connections are not possible with netcat
. You should use something like ucspi-tcp
's tcpserver
tool or leverage xinetd
since you're on Linux.
See: https://superuser.com/questions/232747/netcat-as-a-multithread-server
Consecutive connections could be handled through a shell script that restarts netcat
after it finishes.
Related Topics
How to Get the Architecture of a '.A' File
Difference Between Two .Tar.Gz File Lists on Linux
Use Bash to Read a File and Then Execute a Command from the Words Extracted
Creating PDF Invoices - Are There Any Templating Solutions
What Actually Is $Rpm_Build_Root
What Is the Meaning of Question Marks '' in Linux Kernel Panic Call Traces
Logrotate to Clean Up Date Stamped Files
How to Parse Netstat Command in Order to Get Process Name and Pid from It
Linux - Understanding the Mount Namespace & Clone Clone_Newns Flag
Is There a Good Way to Detect a Stale Nfs Mount
Getting Message "Sudo: Must Be Setuid Root", But Sudo Is Already Owned by Root
When Is Clone() and Fork Better Than Pthreads
How Does the 'Ls' Command Work in Linux/Unix
How to Configure Bash to Handle Crlf Shell Scripts
Linux Shell to Restrict Sftp Users to Their Home Directories