Docker-compose退出代码破坏了while循环

4
我来翻译一下:

我有一个案例:有一个WordPress项目,我需要创建一个脚本来更新插件并将源代码更改提交到分离的分支。在执行此操作时,我遇到了一个奇怪的问题。

输入变量:

    akimset,4.0.3
    all-in-one-wp-migration,6.71

我想要做的是遍历这个变量中的每一行。
    while read -r line; do
      echo $line
    done <<< "$variable"

这段代码之前运行得非常好,但是当我添加了docker-compose的逻辑后,一切开始变得奇怪了。
    while read -r line; do
      docker-compose run backend echo $line
    done <<< "$variable"

现在只有一行被执行,之后这个脚本以0退出并停止迭代。我已经找到了解决方法:
    echo $variable > file.tmp
    for line in $(cat file.tmp); do
      docker-compose run backend echo $line
    done

这段文字的翻译是:“这很好地运行了,它迭代了每一行。现在我的问题是:为什么?ZSH和shell脚本可能有点神秘,而像这样运行在边缘情况下并不是我所经历的新鲜事物,但我想知道为什么成功执行的脚本会中断输入流。”

我不确定,但这是否是因为容器在前台运行且不终止,从而阻塞了后续的 docker-compose run 命令?在这种情况下,您可以尝试执行 docker-compose run -d backend echo $line - ErikMD
3个回答

2

这个问题存在

while read -r line; do
  docker-compose run backend echo $line
done <<< "$variable"

这是Docker分配伪TTY的原因。在第一次执行docker-compose run(第一个循环)后,它使用下一行作为输入访问终端。

您需要在“docker-compose run”命令中传递-T参数,以避免Docker分配伪TTY。然后,工作代码如下:

while read -r line; do
  docker-compose run -T backend echo $line
done < $(variable)

更新

以上解决方案适用于 Docker 版本 18 和 docker-compose 版本 1.17。对于更新版本,参数 -T 不起作用,但您可以尝试:

  1. -d 而不是 -T 以后台模式运行容器,但您将无法在终端中看到 stdout。
  2. 如果您有 docker-compose v1.25.0,请在您的 docker-compose.yml 文件中添加参数 stdin_open: false 到服务中。

1
我能够通过使用不同的循环来解决相同的问题:
for line in $(cat $variable)
do
    docker-compose run backend echo $line
done

0

大约一年前我遇到了一个非常相似的问题,不过当时使用的是 bash shell(命令/问题也略有不同,但同样适用于你的问题)。最终我使用 zsh 写出了这个脚本。

我不确定发生了什么,但这实际上并不是退出代码(您可以通过运行以下命令来确认):

variable=$'akimset,4.0.3\nall-in-one-wp-migration,6.71'
while read line; do docker-compose run backend print "$line"; print "$?"; done <<<($variable)

... 产生了 ...

(akimset,4.0.3
0

我不确定(从哪里来,也许解决这个问题可以回答为什么会发生这种情况。

工作脚本

for line in "${(f)variable}"; do
    docker-compose run backend echo "$line"
done

(f) 标志告诉 zsh 在换行符上分割;"${(f)variable}" 用引号括起来,以防任何空白行丢失。如果您要包含转义序列,而不希望将其转换为相应的值(当我从变量中读取文件内容时经常需要这样做),请设置标志 (fV)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接