旧的Linux内核奇怪的行为



我有一个旧设备,带有最小的自定义linux内核。大约20年前,我们从一家公司购买了这款设备,并对其进行了编程以满足我们的需求。

uname -r
2.4.21

我已经在设备上开发了一个基于文本的UI,并允许通过telnet和串行端口访问它

当使用telnet连接时,调用read -s STR两次,会导致第二次读取被忽略。发生这种情况是因为telnet以"rn"结束线路。

例如:

echo "Enter new password: "; read -s password1
echo "Enter new password again: "; read -s password2 #<--this read returns directly

因此,我的解决方案是在每次读取调用后从stdin读取所有字符。然而,使用串行通信,仅发送"n"作为线路结束。因此,我决定在上面的read调用中添加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

脚本在两个循环后挂起,只有在我按enter键时才会继续。

上次我尝试了以下内容:

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两次不会导致第二次read调用被忽略。

有人对围绕这个问题开展工作有想法吗?

终端正在将每个'\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'抑制它(。

相关内容

  • 没有找到相关文章

最新更新