I know this is not a very descriptive title (suggestions are welcome), but the fact is that I've been pulling my hair over this for hours and I have no clue where the root of the problem might lie.
I wrote a simple Bash script for CLI chat between peers on a local network:
#!/usr/bin/env bash
Usage: ./lanchat <local_ip>:<local_port> <remote_ip>:<remote_port>
set -x
set -o errexit -o nounset -o pipefail
IFS=':' read -a socket <<< "$1"
LOCAL_IP=${socket[0]}
LOCAL_PORT=${socket[1]}
IFS=':' read -a socket <<< "$2"
REMOTE_IP=${socket[0]}
REMOTE_PORT=${socket[1]}
RECV_FIFO=".tmp.lanchat"
trap "rm '$RECV_FIFO'; kill 0" EXIT
mkfifo "$RECV_FIFO"
EDIT: As per @Kamil Maciorowski's suggestion, removing the -q 0
part below solves the issue.
while true; do nc -n -l -q 0 -s "$LOCAL_IP" -p "$LOCAL_PORT" > "$RECV_FIFO"; done &
TMUX_TOP="while true; do cat '$RECV_FIFO'; done"
TMUX_BOTTOM="while IFS= read -r line; do nc -n -q 0 '$REMOTE_IP' '$REMOTE_PORT' <<< $line; done"
tmux new "$TMUX_TOP" ; split -v "$TMUX_BOTTOM"
The machine on IP 172.16.0.2 is a VPS running Debian 11, and on 172.16.0.100 is my local computer running Arch.
When I run the commands manually at the prompt on both sides, I get the desired result, which confirms that there is no issue with network communication and that the logic of the script is correct.
## VPS (Debian) side as follows; exchange IPs for local (Arch) side.
$ mkfifo .tmp.lanchat
$ while true; do nc -n -l -q 0 -s 172.16.0.2 -p 1234 > .tmp.lanchat; done &
$ tmux new "while true; do cat .tmp.lanchat; done" \; split -v "while IFS= read -r line; do nc -n -q 0 172.16.0.100 1234 <<< \$line; done"
## Test communication in both directions: all right; then CTRL-C twice to exit both tmux panels
$ kill %1; rm .tmp.lanchat
when I run both sides as a script, however, only the local side (Arch) prints messages from the server (Debian). The server prints nothing from my local computer. When I trace the execution with set -x
, everything on both sides looks exactly like the commands that I enter manually, with the right values in place of variables.
Now the odd thing is that if I run the script on the Arch side and commands at the prompt (like above) on the Debian side, then everything works fine again. Furthermore, if I execute the script on the Arch side but source it on the Debian side, that too works fine.
Adding verbose output to both nc calls on the Arch side even prints Connection to 172.16.0.2 1234 port [tcp/*] succeeded!
. However, adding a tee log.txt
to the call to nc in listening mode on the Debian side does not capture anything:
#...
while true; do
nc -n -l -q 0 -s "$LOCAL_IP" -p "$LOCAL_PORT" | tee log.txt > "$RECV_FIFO";
done &
#...
I tried establishing the connection in all possible orders between the two peers. I even restarted both the server and my local machine to make sure that there were no orphaned or zombie instances of nc hugging the socket that had somehow evaded detection.
Now, Debian and Arch run different versions of nc. So, on the face of it, it sounds like this could be a possible explanation. But doesn't the fact that sourcing the script on Debian's side works fine rule out that possibility?
What the heck is going on, here?
tmux new "while true; do ...
is not the same command as thattmux new "$TMUX_TOP" \; ...
and for some reason you have single quotes embedded in the TMUX_TOP and TMUX_BOTTOM vars, ones that don't appear in the command you show in the other snippet. But you also don't show theset -x
trace output, so we can't see what exactly happens. – ilkkachu Feb 26 '24 at 08:16<<<
within wouldn't work), and the shell interprets the quotes here. So nevermind. But, in general,foo="'something'"; echo "$foo"
is not the same asecho "something"
, and putting extra quotes is a common mistake people make when trying to store a command in a variable... In any case, it's best to take care to not add unwanted differences when comparing one situation to another. – ilkkachu Feb 26 '24 at 13:43talk
derivatives. I thinkytalk
was one that worked for me - but it was a good number of years ago – Chris Davies Mar 01 '24 at 22:40