WSL2互操作问题导致shell脚本read循环调用Windows程序时提前退出
WSL shell中read循环调用Windows可执行文件提前退出问题解答
根本成因
- WSL的跨系统互操作机制默认会将当前shell的所有标准IO句柄继承给启动的Windows进程,其中就包含
read命令正在迭代读取的标准输入流。 - Windows可执行文件的输入流读取逻辑与Linux原生程序存在差异,调用时会主动消费完输入流内的所有剩余数据。第一次循环调用Windows程序时,它会直接读取完here doc或输入文件中剩余的全部内容,导致下一轮
read执行时无数据可读,循环直接终止。 - 同类问题不会出现在for循环中,是因为for循环会先将所有待遍历值加载到内存后再执行迭代,不需要在循环过程中持续读取输入流,因此不受Windows进程消费输入流的影响。
解决方案
方案1:显式重定向Windows进程的标准输入(最推荐)
直接将Windows可执行文件的输入重定向到/dev/null,完全隔离其对read所用输入流的影响,语法更简洁:
while read -r line; do powershell.exe /C "echo \"${line}\"" < /dev/null done << EOF line 1 line 2 line 3 EOF
方案2:管道注入空输入
通过管道给Windows进程提供空输入,避免其读取到循环的输入流内容:
while read -r line; do echo "" | powershell.exe /C "echo \"${line}\"" done << EOF line 1 line 2 line 3 EOF
方案3:自定义输入文件描述符
将read的输入源绑定到自定义的文件描述符,避免和Windows进程默认继承的标准输入冲突,适合脚本中需要同时处理其他标准输入的场景:
while read -r line <&3; do powershell.exe /C "echo \"${line}\"" done 3<< EOF line 1 line 2 line 3 EOF
内容的提问来源于stack exchange,提问作者kailask
相关产品推荐
相关产品推荐

