Docker RUN指令中composer run-script --list单独执行正常,但管道传给grep时抛出Unable to write output错误
Docker RUN指令中composer run-script --list单独执行正常,但管道传给grep时抛出Unable to write output错误
嘿,这个问题我碰到过!根源其实是grep -q的“安静模式”特性和Composer的输出逻辑冲突了:
当你用管道把composer run-script --list的输出传给grep -q post-install-cmd时,grep -q一旦在输出里匹配到目标字符串,就会立刻终止进程,同时关闭和Composer之间的管道连接。但这时候Composer还没完成所有输出的写入,它尝试往已经被关闭的管道里写内容,就会触发那个Unable to write output的RuntimeException。而单独执行composer run-script --list时,输出是直接写到Docker的构建日志流里,这个流不会提前关闭,所以一切正常。
给你几个解决办法,挑你觉得顺手的来:
方法1:先捕获输出到变量,再匹配
把Composer的输出先存到一个变量里,再对变量内容做grep检查,完全避开管道提前关闭的问题:
RUN set -eux; \ if [ -f composer.json ]; then \ composer dump-autoload --no-dev --classmap-authoritative; \ composer run-script --list; \ # 捕获脚本列表到变量 SCRIPT_LIST=$(composer run-script --list); \ if echo "$SCRIPT_LIST" | grep -q post-install-cmd; then \ echo "Script was found!"; \ fi; \ fi
方法2:用awk替代grep -q,避免提前退出
awk可以读完所有输出再退出,不会提前关闭管道,这样Composer就能写完所有内容:
RUN set -eux; \ if [ -f composer.json ]; then \ composer dump-autoload --no-dev --classmap-authoritative; \ composer run-script --list; \ # 用awk匹配,找到目标后不立刻退出,读完所有输出再返回成功 if composer run-script --list | awk '/post-install-cmd/{found=1} END{exit !found}'; then \ echo "Script was found!"; \ fi; \ fi
方法3:重定向Composer的错误输出(临时规避)
如果你只是不想看到错误日志,也可以把Composer的标准错误重定向到/dev/null,但这只是隐藏错误,不是根本解决:
RUN set -eux; \ if [ -f composer.json ]; then \ composer dump-autoload --no-dev --classmap-authoritative; \ composer run-script --list; \ if composer run-script --list 2>/dev/null | grep -q post-install-cmd; then \ echo "Script was found!"; \ fi; \ fi
个人最推荐方法1,逻辑清晰,也不会有潜在的输出截断问题~
备注:内容来源于stack exchange,提问作者gremo
相关产品推荐
相关产品推荐

