socat wires together two byte streams, whether that is a socket, a file, a pseudo-terminal or a shell command. This guide builds a repeatable way to connect two streams with socat, test a TCP listener on loopback, and recognise the log messages that show what happened. The examples use socat 1.8.0.0 from package version 1.8.0.0-4ubuntu0.1, as installed on this Ubuntu system.
Allow about fifteen minutes. You need a shell and the socat package. The examples are ordinary user commands and use an unprivileged port. Nothing here needs sudo. A listener is a real network service, even when it is intended only for testing, so do not bind one to a public address until you have decided who may connect.
Start by checking the binary, package version and compiled features. This is read-only:
$ command -v socat
/usr/bin/socat
$ socat -V
socat version 1.8.0.0
$ dpkg-query -W -f='${Package} ${Version}\n' socat
socat 1.8.0.0-4ubuntu0.1
The exact feature list is machine-specific. This build reports TCP, UDP, Unix sockets, OpenSSL, PTY, EXEC and SYSTEM support. The installed manual describes version 1.8.0; use socat -V when a script or troubleshooting note depends on a particular build.
Checkpoint: if command -v socat finds nothing, stop here and install the package through your normal system-management process. Do not copy a binary from an unrelated host.
The basic form is:
$ socat [options] <address> <address>
Each address describes one endpoint. Socat opens the first address, opens the second, then transfers bytes in both directions. The dash - is the short name for STDIO, so this command connects the terminal's standard input and output to themselves:
$ printf 'relay-check\n' | socat - -
relay-check
Exit status 0 means the relay ended through normal end-of-file or an inactivity timeout. Socat normally prints only fatal, error and warning messages. Add -d for notices, or use -d -d when you need the useful lifecycle messages without the full debug stream.
Do not confuse command-line options with address options. -d -d belongs before the two addresses. Options such as reuseaddr and fork belong after a comma in an address, as in TCP-L:PORT,reuseaddr,fork.
Open a second terminal, then start this listener in it:
$ socat -d -d TCP-L:39127,reuseaddr,fork SYSTEM:'cat'
2026/09/27 03:07:17 socat[PID] N listening on ...:39127
TCP-L is the documented abbreviation for TCP-LISTEN. The listener accepts TCP connections on port 39127. reuseaddr permits reuse of a recently used local address, and fork lets the listener continue accepting later connections. SYSTEM:'cat' starts a shell command for each connection and connects that command's standard input and output to the socket.
The address above does not force loopback. On this build, the listener may report an IPv6 wildcard address and can be reachable through more interfaces than you intended. For a local-only test, bind explicitly:
$ socat -d -d TCP4-LISTEN:39127,bind=127.0.0.1,reuseaddr,fork SYSTEM:'cat'
Choose a free high port, and replace 39127 consistently if it is already in use. This process stays in the foreground. Press Ctrl-C when finished; that is the undo action and removes no files or persistent configuration.
From another terminal, send one line to the loopback listener:
$ printf 'tcp-check\n' | socat - TCP4:127.0.0.1:39127
tcp-check
The first address is standard input and output. The second is an active TCP connection. The echoed line proves that the client, listener and per-connection cat process all exchanged data.
Checkpoint: inspect the listener's diagnostic output. A successful connection includes messages about accepting the connection, forking a child and starting a data-transfer loop. The parent should return to listening. If the client exits with status 0 but you did not see an accept message, check that both commands used the same address family, address and port.
Use the smallest logging level that answers the question:
$ socat -d -d TCP4-LISTEN:39127,bind=127.0.0.1,reuseaddr,fork SYSTEM:'cat'
One -d includes notice messages. Two include information messages such as the file descriptors and transfer-loop lifecycle. Three and four levels add increasingly detailed internal and system-call diagnostics. The manual labels the severities F, E, W, N, I and D. If the process reports an error and exits, first fix the address, permissions or port conflict; -s makes some errors non-fatal, but it is not a repair option and can leave a relay running after an address has failed.
For a short capture, write logs to a file with -lf:
$ socat -d -d -lf /tmp/socat-test.log TCP4-LISTEN:39127,bind=127.0.0.1,reuseaddr,fork SYSTEM:'cat'
This changes the contents of the named log file. Choose a temporary path you control, and do not redirect diagnostics into a sensitive or shared location. Remove the temporary file after checking it if it contains information you do not want to retain.
TCP is only one address family. The same two-stream model supports local Unix sockets, files, pipes, processes and TLS. A few useful shapes from the installed manual are:
UNIX-CONNECT:/run/example.sock connects to an existing Unix stream socket.UNIX-LISTEN:/tmp/example.sock,fork listens on a Unix socket and can fork for clients.OPENSSL:host.example:443 opens a TLS client connection. Certificate and hostname checks still need deliberate configuration.EXEC:/path/to/program runs a program with a socket-like byte stream.PTY,link=/tmp/example-pty creates a pseudo-terminal link and changes local device state.Treat EXEC, SYSTEM and SHELL as code execution, not as harmless endpoint names. Keep commands and arguments fixed where possible, quote shell data, and do not pass untrusted input into a shell address. Creating a listener, changing a Unix socket path, opening a PTY or forwarding traffic to a third party can affect other users and services. Test in a disposable environment and stop the process with Ctrl-C when done.
The package also installs filan and procan. They are companion diagnostics, not alternate relay modes. filan reports active file descriptors and their socket or path information; procan reports process parameters. Ask each command for its own help before using a more specialised option:
$ filan -h
Analyze file descriptors of the process
$ procan -h
Analyze system parameters of process
Use these when a relay appears to have opened the wrong kind of endpoint or inherited an unexpected descriptor. They inspect the process and do not reconfigure the listener.
EXEC, SYSTEM, PTY and forwarding examples behind an explicit safety review.