为何Bash脚本中使用tee会导致git clone执行挂起?
问题:为何tee会导致git clone执行挂起?
我编写了如下Bash脚本:
#!/bin/bash -xe set -xe function build() { git clone --mirror https://github.com/digi-embedded/u-boot.git } time build $@ |& tee /tmp/build.log
执行./build.sh时脚本出现挂起,添加GIT_CURL_VERBOSE=1 GIT_TRACE=1参数后查看日志,发现git clone卡在fetch阶段。但单独执行git clone --mirror https://github.com/digi-embedded/u-boot.git命令时一切正常,移除脚本中的tee重定向语句后,脚本又能正常运行。请问为何tee会导致git clone执行失败?
分析与解决
核心原因:Git与管道交互的stdin阻塞问题
Git在clone、fetch这类操作中,会检测标准输入(stdin)是否为终端(tty):
- 单独执行git命令时,stdin对接终端,Git检测到是tty,会跳过读取stdin的操作,正常执行。
- 但用
|& tee把输出重定向后,stdin变成了管道而非tty,Git会尝试从stdin读取数据,而管道没有任何输入,导致Git一直等待,脚本就挂起了。
验证场景
你可以手动复现这个阻塞:
# 此命令会卡住,因为Git等待stdin输入 git clone --mirror https://github.com/digi-embedded/u-boot.git | tee test.log
而如果给Git明确关闭stdin,就不会卡:
# 关闭stdin,Git跳过读取操作,正常执行 git clone --mirror https://github.com/digi-embedded/u-boot.git < /dev/null | tee test.log
修复脚本的方法
修改build函数里的git命令,添加< /dev/null强制关闭stdin,让Git不再尝试读取输入:
#!/bin/bash -xe set -xe function build() { git clone --mirror https://github.com/digi-embedded/u-boot.git < /dev/null } time build $@ |& tee /tmp/build.log
内容的提问来源于stack exchange,提问作者rosewater
相关产品推荐
相关产品推荐

