When running socat as a TCP server with fork mode, many developers encounter premature termination when the client disconnects. The core issue manifests in the logs as:
socat[4746] N socket 1 (fd 4) is at EOF
socat[4746] N exiting with status 0
This behavior occurs because socat's default behavior is to terminate when it detects EOF on the socket connection, even in fork mode. The 3-second delay you're experiencing is the time needed to restart the socat listener.
Here are three proven approaches to maintain socat availability:
# Solution 1: Keep the file descriptor open
socat -v -d -d tcp-listen:2600,reuseaddr,fork,keepalive \
exec:"/usr/bin/cec-client",nofork
# Solution 2: Use systemd or supervisor for automatic restart
[Unit]
Description=Persistent Socat Service
After=network.target
[Service]
ExecStart=/usr/bin/socat -v -d -d tcp-listen:2600,reuseaddr,fork \
exec:"/usr/bin/cec-client"
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
# Solution 3: Advanced bash wrapper
#!/bin/bash
while true; do
socat -v -d -d tcp-listen:2600,reuseaddr,fork \
exec:"/usr/bin/cec-client"
sleep 1
done
The keepalive
option enables TCP keepalive packets, while nofork
prevents child process termination. For production environments, I recommend combining both the systemd approach and TCP keepalive:
socat -v -d -d tcp-listen:2600,reuseaddr,fork,keepalive,keepidle=60,keepintvl=60,keepcnt=5 \
exec:"/usr/bin/cec-client $CEC_CLIENT_ARGS",pty,stderr
The keepidle
, keepintvl
, and keepcnt
parameters provide fine-grained control over TCP keepalive behavior, helping maintain connections through network interruptions.
To verify your solution works:
# Test connection persistence
for i in {1..10}; do
echo "Test $i" | nc localhost 2600
sleep 0.5
done
# Check process lifetime
watch -n 1 'ps aux | grep "[c]ec-client"'
You should see a single persistent socat process handling all connections without the 3-second restart delay.
When running socat with fork mode for TCP services, many developers encounter premature termination when the client disconnects. The core issue manifests like this:
socat -v -s -d -d tcp-listen:2600,reuseaddr,fork exec:"/usr/bin/cec-client $CEC_CLIENT_ARGS"
The logs show unwanted EOF detection:
2023/11/15 14:22:33 socat[8831] N socket 1 (fd 4) is at EOF
2023/11/15 14:22:34 socat[8831] N exiting with status 0
Common approaches like ignoreeof
or timeout adjustments often don't work because:
- The EOF signal comes from the underlying file descriptor
- Forked processes inherit socket states
- TCP connection teardown triggers automatic cleanup
This combination addresses multiple failure points:
socat -d -d \
TCP-LISTEN:2600,reuseaddr,fork,keepalive,keepidle=10,keepintvl=10,keepcnt=2 \
EXEC:"/usr/bin/cec-client",pty,stderr,nofork
Key improvements:
keepalive
parameters maintain TCP connection trackingpty
creates persistent pseudo-terminalnofork
prevents file descriptor inheritance issues
For production deployments, consider socket activation:
# socat.socket
[Unit]
Description=Socat Persistent Socket
[Socket]
ListenStream=2600
Accept=yes
[Install]
WantedBy=sockets.target
# socat@.service
[Unit]
Description=Socat Instance
[Service]
ExecStart=/usr/bin/socat -d -d FD:0 EXEC:"/usr/bin/cec-client"
StandardInput=socket
StandardError=syslog
Essential verification commands:
# Check socket states
ss -tulnp | grep 2600
# Verify process persistence
watch -n 1 'ps aux | grep "[c]ec-client"'
# TCP dump analysis
tcpdump -i any port 2600 -vvv