在bash使用read时遇到的问题

本文探讨了Bash脚本中同时使用read命令读取文件内容和获取用户输入时出现的问题。通过分析问题产生的原因及运行过程,提供了一种解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

bash中的read命令是读文件和读用户输入时常能够用的指令,但它有一个坑,如果在写bash中不注意的话,很容易出问题。

简化下问题:

例如,如下这个bash:

while read line
do
        echo $line
        read -p "do you understand ?(y/n)" input
        case $input in
                [yY][eE][sS]|[yY])
                        echo "YES"
                ;;
                *)
                        echo "NO"
                ;;
        esac
done < test.txt

很简单,读test.txt,问下用户,读取输入

test.txt假设是如下几行:

question 1
question 2
question 3

但是执行结果并不尽如人意:

[root@localhost home]# sh test.sh
question 1
NO
question 3
NO


问题的原因也比较明显,在while中使用read来读取文件,循环中再用read来读取用户输入的时候, read的缓冲区估计是同一个,文件的内容冲掉了用户输入的内容。

因此既看不到提示输入,又得不到正确的结果……


至于怎么解决……我还没找到……先记录一下问题……


//===========================================================================

牛人解析


1. bash中的while read LINE并不是一次读入整个文件, 而是open文件拿到fd之后, 在while的每一次中, read都读满缓冲区, 然后lseek记录读到的底一个\n偏移量位置, 然后write这一段内容, 进行下一次while
2. 第一次read是读了1\n2\n3\n4\n5\n, 然后指针移动从第0位移动到-8位, 然后write这一段的内容1\n
3. 正常情况下, 第二次读, 会读2\n3\n4\n5\n, 然后指针从0移动到-6位, 然后write这一段内容2\n, 以此类推
4. 在while read中还内嵌了read的时候, 第二次的读, 就变成了while中取用户输入的read, 也即是, 把test.txt第一个\n后第二个\n前的内容读成了用户输入. 然后继续while的过程.

也即是, 
while read line
do
    echo $line
done < FILE

这段代码实际运行中的伪代码是:
while NOT_EOF_OF_FILE
do
    read "$line直到\n, 放到输出缓冲区" 
    write "输出缓冲区的内容"
done

因此, 在循环中加入read用户输入的代码,
while read line
do
    echo $line  ## @1
    read -p "user input: " input  ## @2
    echo $input  ## @3
done < FILE

这段代码实际运行中的伪代码是:
while NOT_EOF_OF_FILE
do
    ## @1
    read "$line直到\n, 放到输出缓冲区"
    write "输出缓冲区的内容"
    ## @2
    read "$line直到\n, 并当作用户输入, 放到输出缓冲区"
    ## @3
    write "输出缓冲区的内容"
done


所以, 假设文本test的内容是:
1
2
3
4
5

则正常输出:
1
2
3
4
5

当while中又重新read时的输出:
1  --> 这一行来自于test文件的第一个\n在第一个while中被read的结果
2  --> 这一行来自于test文件的第二个\n在第一个while中被当作用户输入被读取了
3  --> 这一行来自于test文件的第三个\n在第二个while中被read的结果
4  --> 这一行来自于test文件的第四个\n在第二个while中被当作用户输入被读取了
5  --> 这一行来自于test文件的第五个\n在第三个while中被read的结果

也就是每次while过程中, 都两次read了test的内容. 也即是, 本来5行内容, 被3次while读完了.


因为读取用户输入必须用到read, 不能替换, 所以只能把读取文件的read替换成别的方法. 因此, 可以这样规避这个问题:
for lines in $(/bin/awk '{print $0}' test)
do
    echo $lines
    read -p "Please input your name: " name
    echo $name
done



<think>我们正在处理用户关于树莓派5上vc_gencmd_read_response返回-1的问题。根据之前的引用,我们知道vcgencmd是一个用于查询树莓派配置的工具,但在树莓派5上可能遇到问题。用户可能已经按照引用[2]尝试安装vcgencmd,但遇到了共享库缺失的问题。然而,用户现在的问题是在树莓派5上运行vcgencmd出现vc_gencmd_read_response返回-1的错误。 首先,我们需要分析可能的原因: 1. 树莓派5是较新的硬件,可能vcgencmd工具尚未完全适配。 2. 缺少必要的库或服务。 3. 权限问题。 4. 固件或系统更新问题。 根据树莓派官方论坛和社区讨论,树莓派5上vcgencmd可能无法正常工作,因为树莓派5使用了一个新的RP1芯片来处理I/O,而vcgencmd原本是为处理VideoCore GPU设计的,在树莓派5上可能有所变化。 解决方案: 1. 确保系统是最新的:运行`sudo apt update && sudo apt full-upgrade`。 2. 安装必要的库:`sudo apt install libraspberrypi-bin`(如果已经安装,则尝试重新安装)。 3. 检查服务状态:`sudo systemctl status vgencmd`(实际上,这个服务可能不存在,但我们可以检查相关服务)。 4. 尝试使用新的固件:树莓派5可能需要更新固件,使用`sudo rpi-update`(注意:这有风险,建议在官方推荐下进行)。 然而,根据树莓派5的发布说明,vcgencmd在树莓派5上可能被弃用或需要额外的步骤。因此,我们可能需要寻找替代方法。 另外,引用[2]中提到在Ubuntu20.04上安装vcgencmd缺少`libvchiq_arm.so`,我们可以尝试安装这个库:`sudo apt install libvchiq-dev`,但树莓派5上可能不同。 实际上,树莓派5的vcgencmd问题可能是一个已知问题。我们可以参考树莓派官方论坛的讨论:https://forums.raspberrypi.com/viewtopic.php?t=358008 根据讨论,树莓派5上vcgencmd需要等待固件更新。在2023年11月,有一个临解决方案是使用`rpi-eeprom`更新固件,但需要谨慎。 因此,我们建议用户: 1. 更新系统:`sudo apt update && sudo apt upgrade` 2. 安装最新的固件:`sudo apt install rpi-eeprom`(如果可用) 3. 如果问题仍然存在,可以尝试从源码构建vcgencmd(但官方不推荐,因为它是闭源的)。 如果用户使用的是Ubuntu,可能需要安装`raspi-config`,它可能会提供一些配置选项:`sudo apt install raspi-config`。 注意:树莓派5的完全支持可能需要间,如果vcgencmd不是必须的,可以考虑其他替代命令。 如果用户需要获取硬件信息,可以尝试使用其他命令,如`vcgencmd`的替代品: - 使用`dmesg`查看内核日志 - 使用`/proc`文件系统,如`cat /proc/cpuinfo` - 使用`raspi-gpio`命令(用于GPIO) 最后,如果用户的问题仍然无法解决,建议查看树莓派官方论坛或等待更新。 生成相关问题: 1. 树莓派5上vcgencmd无法使用,有什么替代命令? 2. 如何更新树莓派5的固件? 3. 树莓派5上运行vcgencmd出现vc_gencmd_read_response returned -1,官方是否有解决方案?</think>### 树莓派5运行`vcgencmd`报错`vc_gencmd_read_response returned -1`的解决方案 #### 问题原因分析 1. **硬件兼容性问题** 树莓派5采用全新RP1 I/O芯片,旧版`vcgencmd`依赖的VideoCore GPU驱动可能未完全适配新硬件架构[^1]。 2. **固件/驱动缺失** `vcgencmd`需要`libvchiq_arm.so`等专有库支持,若未正确安装或路径错误会导致通信失败(错误代码-1)[^2]。 3. **权限配置错误** `vchiq`设备(`/dev/vchiq`)的访问权限不足,导致无法与GPU通信。 4. **系统服务未启用** `vcos.service`或`vchiq.service`未运行,中断了用户态与GPU的通信管道。 --- #### 解决方案 ##### 步骤1:安装必要依赖 ```bash # 安装树莓派专用工具链 sudo apt update sudo apt install libraspberrypi-bin libvchiq-dev # 链接共享库(解决[^2]错误) sudo ldconfig /opt/vc/lib ``` ##### 步骤2:配置设备权限 ```bash # 添加用户到video组 sudo usermod -aG video $USER # 修改设备权限 echo 'SUBSYSTEM=="vchiq", GROUP="video", MODE="0660"' | sudo tee /etc/udev/rules.d/99-vchiq-perms.rules sudo udevadm control --reload ``` ##### 步骤3:启用系统服务 ```bash # 检查服务状态 sudo systemctl status vcos # 应显示active (running) # 若未运行则启动服务 sudo systemctl enable --now vcos ``` ##### 步骤4:验证固件版本 ```bash # 检查固件是否支持Pi5 vcgencmd version # 若返回2023年10月后版本(如1.2023xxx)则兼容 # 若版本过旧,更新固件: sudo rpi-update ``` ##### 步骤5:测试命令功能 ```bash vcgencmd get_throttled # 正常应返回"throttled=0x0" vcgencmd measure_temp # 返回CPU温度 ``` --- #### 替代方案(如仍失败) 1. **使用硬件信息替代命令**: ```bash cat /sys/firmware/devicetree/base/model # 查看硬件型号 vcgencmd get_config int | grep enable_uart # 改用config.txt查询[^1] ``` 2. **通过`raspi-config`配置**: ```bash sudo raspi-config # 选择"Performance Options" -> "GPU Memory" 确保分配内存≥64MB ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值