旧Linux内核奇怪的行为

时间:2014-06-06 07:44:25

标签: linux bash timeout

我有一个带有最小自定义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不会导致第二次读取调用被忽略。

有没有人知道围绕这个问题的工作?

1 个答案:

答案 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')。