我有一个带有最小自定义Linux内核的旧设备。我们在大约20年前从一家公司购买了该设备并对其进行了编程以满足我们的需求。
uname -r
2.4.21
我在设备上开发了基于文本的UI,并允许通过telnet和串口访问它。
使用telnet连接时,调用read -s STR
两次,导致第二次读取被忽略。这是因为telnet以"\r\n"
结束行。
e.g:
echo "Enter new password: "; read -s password1
echo "Enter new password again: "; read -s password2 #<--this read returns directly
所以我的解决方案是在每次读取调用后从stdin读取所有字符。
但是,仅使用串行通信"\n"
作为行结尾发送。所以我决定在上面的读取调用中添加1秒超时。
所以,我基本上最终得到了这个:
echo "Enter new password: "; read -s password1
read -t 1 -n 1000 ignore
echo "Enter new password again: "; read -s password2
read -t 1 -n 1000 ignore
令我惊讶的是,read -t 1
有时会阻止。所以我运行以下内容来说明这种行为:
set -x
while true;
do
read -t 1 -n 10000 STR
echo "timeout"
sleep 5
done
脚本在2次循环后挂起,只有在按下回车键时才会继续。
最后我尝试了以下内容:
set -x
unset STR
while true;
do
read -s -n 1 char
if [[ $char == $'\r' ]]
then
read -s -n 1 ignore
break
elif [[ $char == $'\n' ]]
then
break
fi
STR=$STR$char
done
这导致:
++ true
++ read -s -n 1 char
]][[ a == \
++ [[ a == \
]]
++ STR=a
++ true
++ read -s -n 1 char <-------- HERE I PRESSED ENTER
]][[ '' == \
++ [[ '' == \
]]
++ STR=a
++ true
++ read -s -n 1 char
因此ENTER
或"\n"
正在转换为''
,因此它不会突破循环。
在较新的设备上,我们可以更好地控制内核
uname -r
2.6.24.6
问题没有发生,即两次调用read不会导致第二次读取调用被忽略。
有没有人知道围绕这个问题的工作?
答案 0 :(得分:1)
终端正在将每个'\ r'翻译成'\ n',所以你看两者之间没有区别。您可以使用stty igncr
完全忽略CR。有了这个,你的第一种方法应该有效:
stty igncr
echo "Enter new password: "; read -s password1
echo "Enter new password again: "; read -s password2
stty sane
最后stty sane
可能没有必要。
如果该方法不起作用,请尝试使用stty -icrnl
代替(但这样,$password1
和$password2
最后会有\r
;您可以取消它与tr -d '\r'
)。