Docker构建中管道Shell命令执行失败问题排查
问题场景
Docker构建文件中使用以下命令时:
RUN 'echo "y" | /usr/bin/task'
构建抛出错误:
=> ERROR [tool_config 9/11] RUN 'echo "y" | /usr/bin/task' 0.2s
[tool_config 9/11] RUN 'echo "y" | /usr/bin/task':
#15 0.164 /bin/sh: echo "y" | /usr/bin/task: 未找到executor failed running [/bin/sh -c 'echo "y" | /usr/bin/task']: exit code: 127
该命令在容器内手动执行正常,且task命令已确认安装。去掉引号后使用:
RUN echo "y" | /usr/bin/task
则出现新错误:
=> ERROR [tool_config 9/11] RUN echo "y" | /usr/bin/task 0.2s
[tool_config 9/11] RUN echo "y" | /usr/bin/task:
#15 0.176 无法在/root目录找到配置文件
#15 0.176
#15 0.176 是否需要创建一个示例/root/.taskrc文件,让Taskwarrior继续运行?(yes/no) 无匹配项。executor failed running [/bin/sh -c echo "y" | /usr/bin/task]: exit code: 1
错误原因及修复
第一个错误(命令未找到)
用单引号包裹整个命令后,Docker会将echo "y" | /usr/bin/task当作单个完整的命令名去查找,而不是交给shell解析管道|的逻辑,因此shell找不到这个不存在的命令,返回127错误。
去掉外层单引号是正确的修正方向,但又触发了第二个问题。
第二个错误(交互输入不被识别)
Taskwarrior的交互提示要求输入精确匹配值,在Docker构建的非交互式shell环境中,管道传递的y可能因为输入流处理方式问题,没有被Taskwarrior正确识别。
最稳妥的解决方式是使用Taskwarrior自带的非交互式参数,直接跳过交互确认:
RUN /usr/bin/task --yes
--yes参数会自动对所有需要确认的提示回复"yes",完全规避交互环节。
如果一定要通过管道模拟输入,可改用printf传递更规范的输入(带换行符):
RUN printf "y\n" | /usr/bin/task
内容的提问来源于stack exchange,提问作者StevieD

