2

I've been trying to read (on raspbian OS) answer from telnet server using bash script nc or /dev/tcp/. But the server answers very slow, I have to wait ~3 seconds for the answer. Here is my working code, what I typed manually and I want to use it in automated bash script:

telnet 192.168.1.225 233
Trying 192.168.1.225...
Connected to 192.168.1.225.
Escape character is '^]'.
7
Voltage: 222.2, Current: 0.0 Power: 0, Energy: 176
7
Voltage: 222.0, Current: 0.0 Power: 0, Energy: 176
q
^]
telnet> quit
Connection closed

"7" is my command to server and "Voltage.." is the answer. So I googled, and tried the following bash script:

#!/bin/bash
exec 3<>/dev/tcp/192.168.1.225/233
echo "sending 7"
echo -en "7\n" >&3
sleep 20 #wait  enough time for answer
echo "waiting..."
#read -r RESPONSE <&3
#RESPONSE="$(cat <&3)"
#RESPONSE="${cat <&3}"
RESPONSE="`cat <&3`"
echo "waiting..."
echo "Response is: $RESPONSE"

As you can see I tried multiple ways, but none of them worked. When I execute the script I get this:

sending 7
waiting...
^C

^C-> The script does not answer, and I have to kill it using ctrl+c

I want to get the message and parse the numeric values. I think the problem is with cat, but I couldn't figure out, how to use it properly with delayed answer.

I tried execute my script in shell:

root@raspberrypi:/home/pi/gabor# exec 3<>/dev/tcp/192.168.1.225/233
root@raspberrypi:/home/pi/gabor# echo -en "7\n" >&3
root@raspberrypi:/home/pi/gabor# cat <&3
Voltage: 223.4, Current: 0.0 Power: 0, Energy: 175
^C

How can I get the answer?

Update1: I tried printf '7\n' >&3, no change. Update2: I waited more time and got the following result:

sending 7

20 secs after starting the script

waiting...

~3 minutes after starting the script

waiting...
Response is: Voltage: 226.4, Current: 0.0 Power: 0, Energy: 177

1 Answers1

0

If it's a buffering issue, reading one character at a time may solve the problem.

#!/bin/bash

exec 3<>/dev/tcp/192.168.1.225/233
echo 7 >&3
IFS=''
while read -u 3 -N 1 char; do
    [[ $char == $'\n' ]] && break
    RESPONSE+=$char
done
IFS=$' \t\n'
exec 3>&-

echo $RESPONSE

The above uses the shell's builtin read to consume one character at a time, and breaks out of the loop if a newline is read. The IFS must not contain newline, given that the loop needs to check for it. After leaving the loop, IFS is reset and the connection closed.

dan4thewin
  • 1,134
  • 7
  • 10
  • Thank You very much for your answer! I executed it and it didn't work. But, for debug purposes I inserted "echo $char" before "done". And it worked". I commented out this inserted line and worked again. So I don't understand what happens. Now I deleted "echo $char", remained only "#" and it works. I deleted this line and the script didn't work. Now after few minutes it works without any inserted line, so as original. I'm confused. I'm learning linux (I'm electrical engineer btw.), and sometimes it is not easy to understand this linux world. Thanks for help! – Gabor Kovacs Feb 24 '16 at 21:08
  • At a guess, the indeterminism is coming from something outside of bash, perhaps the serving program. Adding and/or removing `echo`s and comments as you describe shouldn't cause the script to stop working. Do you have the source for the serving program? – dan4thewin Feb 24 '16 at 23:00
  • I tried again the code, which was working 2 days ago, but now doesn' work. – Gabor Kovacs Feb 27 '16 at 09:24
  • I tried again the code, which was working 2 days ago, but now doesn' work. I succesfully got to work again, on the same way (insert echo), again removed, and works... I wrote the source of the remote server. The server is running on STM32F103 MCU connected with ESP2866 WiFi modul. I don't think the problem is with the server side, because it works fine with standard telnet connection. I don't undarstand this weird behaviour of the bash script, why is it influenced by echo-s? OS: Linux raspberrypi 4.1.17-v7+ – Gabor Kovacs Feb 27 '16 at 09:30