curl管道执行bash脚本时docker-compose导致后续命令终止的原因分析
问题原因与解决方案
这个问题确实是docker-compose exec -T导致的,根源出在管道执行时的标准输入(stdin)继承逻辑上:
- 当你用
curl ... | bash的方式执行脚本时,bash的标准输入来自curl的管道,bash会逐行读取管道里的内容来执行online_install.sh的命令。 - 执行到
./install.sh时,install.sh进程会继承bash的stdin(也就是这个管道)。而docker-compose exec -T默认会继承父进程的stdin,尝试读取数据传递给容器内的命令。 - 虽然此时
online_install.sh的内容已经全部被bash读取完毕,但管道的stdin仍处于打开状态。docker-compose exec -T在读取stdin时,会意外关闭这个流,导致bash后续尝试读取剩余命令(也就是rm install.sh)时,误以为stdin已经结束,直接退出,不再执行后续命令。 - 而直接下载
online_install.sh后运行时,stdin是终端,docker-compose exec -T即使读取stdin,也只会读取终端输入(无输入就直接得到EOF),不会影响父bash进程的stdin,所以后续命令能正常执行。
解决办法
有两种简单的修复方式:
方式1:调用install.sh时重定向stdin到/dev/null
修改online_install.sh的内容:
curl https://example.com// --output install.sh # 重定向install.sh的stdin到/dev/null,避免它继承管道的stdin ./install.sh < /dev/null rm install.sh
方式2:在docker-compose exec命令中重定向stdin
修改install.sh里的对应命令:
something_staff # 把docker-compose的stdin重定向到/dev/null,避免读取父进程的流 docker-compose exec -T <some_container_name> <some command> < /dev/null something_staff
两种方式都能切断docker-compose对管道stdin的依赖,让online_install.sh执行完install.sh后继续执行删除命令。
内容的提问来源于stack exchange,提问作者fastbloodjke
相关产品推荐
相关产品推荐

