There are some great communication protocols (MQTT, RabbitMQ, ReDis …) that are excellent for passing data between nodes.
For applications where you only need to do simple communications a couple of lines of Bash can be used with TCP or UDP sockets.
In this blog I wanted to document UDP/TCP communications using Linux Bash commands to:
- define periodic 1-way communications
- use progress bars to show data from remote nodes
- remotely send commands to a Raspberry Pi
- setup simple TCP backdoors
NC (NetCat) – for TCP and UDP Connections
In theory you should be able to create a input read via something like:
echo $(read < /dev/udp/127.0.0.1/9999)
Then do a write using:
echo "some text" > /dev/udp/127.0.0.1/9999)
Unfortunately Linux device connections are not fully reliable, especially on the read or listening side. However the write component appears to be fairly solid. Luckily there is a solid solution using the nc (NetCat) command line utility. The nc utility is typically preloaded on most Linux systems.
The nc utility supports both UDP (-u option) and TCP (default) connections.
To setup a UDP listener, use the IP address of the listener node, and select the -k option to allow multiple connections to occur:
nc -u -l -k 192.168.0.111 9999
For this example the listener’s IP is: 192.168.0.111, and port 9999 is used.
To do manual writes from the command line, enter:
nc -u 192.168.0.111 9999
To send data from a script there are two methods, either using nc or writing to the device:
# writing via nc, -w0 send only 1 message
echo "456" | nc -u -w0 192.168.0.111 9999
# writing via device:
echo "456" > /dev/udp/192.168.0.111/9999
Multiple Writes and Zenity Progress Dialogs
Zenity is command line dialog utility that is typically preinstalled on most versions of Linux.
The data that is sent to the UDP listener can be piped to Zenity progress bar:
nc -u -l -k 192.168.0.111 9999 | zenity --progress --title="Remote Data"
A script to send seconds every second would be:
#!/bin/bash
echo "Press [CTRL+C] to stop..."
(
while :
do
# $(date +'%S') seconds" | nc -u -w0 192.168.0.111 9999
echo "$(date +'%S')" | nc -u -w0 192.168.0.111 9999
sleep 1
done
)
When the script echos an integer the progress bar will be updated with the integer value. An echo string starting with a “#” will update the text above the bar.

The progress bar is from 0-100%, but the integer value can be re-scaled to make the information clearer. For example to re-scale 0-60 secs to 0-100:
echo "$(date +'%S')*100/60" | bc | nc -u -w0 192.168.0.111 9999
YAD – for Multiple Progress Bars
YAD (Yet Another Dialog) is a command line GUI utility that offers a little more functionality than Zenity. To install YAD on Raspberry Pi’s and Ubuntu: sudo apt-get install yad
A bash command with a UDP listener with YAD 2-bars would be:
nc -u -l -k 192.168.0.111 9999 | yad --multi-progress \
--bar="CPU Idle" --bar="CPU Temp" --title="Remote CPU Info"
The CPU Idle Time can be found by:
top -n 1 | grep %Cpu | awk '{print $8}'
93.8
The CPU Temperature on a PC can be found by:
sensors | grep CPU | awk '{print substr($2,2,4)}'
44.0
A script to send the CPU Idle Time and Temperature to the UDP listener is:
#!/bin/bash
echo "Press [CTRL+C] to stop..."
(
while :
do
cpuidle=$(top -n 1 | grep %Cpu | awk '{print $8}')
echo "1:"$cpuidle | nc -u -w0 192.168.0.111 9999
cputemp=$(sensors | grep CPU | awk '{print substr($2,2,4)}')
echo "2:"$cputemp | nc -u -w0 192.168.0.111 9999
echo "2:#"$cputemp" Deg C" | nc -u -w0 192.168.0.111 9999
sleep 5
done
)

For YAD multiple progress bars, an echo of 1: is for bar 1, 2: is for bar 2 etc. Echo-ing “2:# ” updates the text for the 2nd bar.
NC is not the same on Rasp Pi
I found that on the Rasp Pi the nc listening functions would not pass any information to bash scripts. Manual mode still works to view messages, but the messages can’t be piped to other commands.
This mean that things like the Zenity and YAD progress bars would not work on a Raspberry Pi. For many applications this may not be a big problem because the Rasp Pi can still send information via nc.
NC vs. NCAT
The ncat utility is very similar to nc but it offers the ability to run commands. By default nc is preloaded on most systems, but ncat needs to be installed. Installing ncat will vary based on your OS.
The ncat utility allows you to make backdoors so be careful of its use.
To create a backdoor simply (via TCP), define the ncat -c (execute command option) to be /bin/bash:
ncat -l -k 192.168.0.108 9999 -c /bin/bash
If on a remote node you enter: ncat 192.168.0.108 , you can start typing commands that are run on the remote node with the results echoing back. Very cool for test system but super dangerous for real systems.
Remotely Toggle a Rasp Pi GPIO Pin

Rather than opening up the system totally fixed commands can be defined. For example to toggle pin 7 on a Rasp Pi. A listener script is run:
ncat -l -k 192.168.0.108 9999 -c "gpio toggle 7"
A remote button GUI script could be used in conjunction with the listener script to toggle the GPIO pin:
#!/bin/bash
#
# Toggle a Rasp Pi GPIO pin
rc=1 # OK button return code =0 , all others =1
while [ $rc -eq 1 ]; do
ans=$(zenity --info --title 'Remote Connect to Pi' \
--text 'Toggle GPIO Pin' \
--ok-label Quit \
--extra-button TOGGLE \
)
rc=$?
echo "${rc}-${ans}"
echo $ans
if [[ $ans = "TOGGLE" ]]
then
echo "Toggle Pin"
nc -w0 192.168.0.108 9999
fi
done

Send a Command String to Run Remotely

For this example the Rasp Pi is setup to be TCP listener, and the command (-c option) is /bin/bash, so this allows the remote PC to send custom commands:
ncat -l -k 192.168.0.108 9999 -c /bin/bash
On the remote system a bash script is created with 2 buttons and the custom commands are sent to the Pi to run:
#!/bin/bash
#
# Toggle two Rasp Pi GPIO pins
rc=1 # OK button return code =0 , all others =1
while [ $rc -eq 1 ]; do
ans=$(zenity --info --title 'Remote Connect to Pi' \
--text 'Toggle GPIO Pins' \
--ok-label Quit \
--extra-button Pin2 \
--extra-button Pin7 \
)
rc=$?
echo "${rc}-${ans}"
echo $ans
if [[ $ans = "Pin2" ]]
then
echo "gpio toggle 2" | nc -w0 192.168.0.108 9999
elif [[ $ans = "Pin7" ]]
then
echo "gpio toggle 7" | nc -w0 192.168.0.108 9999
fi
done

On systems other than Rasp Pi, the nc command can also be used to run remote programs by:
nc -u -l -k 192.168.0.111 9999 | awk '{ system($1 " " $2 " " $3 " " $4)}'
Final Comments
In this blog I’ve kept things focused on TCP/UDP communications with bash script but you could easily include Arduino, Python and Node-Red as either clients or servers.