从docker-expose退出while循环中退出代码

时间:2018-07-31 15:18:08

标签: while-loop docker-compose zsh

我有一个案例:在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脚本编写可能有点繁琐,并且在这种情况下运行对我来说并不是什么新鲜事,但是我想知道为什么成功执行的脚本会破坏输入流。

3 个答案:

答案 0 :(得分:0)

大约在一年前,我遇到了一个几乎相同的问题,尽管外壳是bash(命令/问题也稍有不同,但是它适用于您的问题)。我最终在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"用引号引起来,这样任何空白行都不会丢失。如果您要包含要转换为相应值的escap序列(从变量读取文件内容时经常需要的值),请设置标志(fV)

答案 1 :(得分:0)

这个问题

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

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

您必须将-T参数传递给'docker-compose run'命令,以避免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。

答案 2 :(得分:0)

我能够通过使用不同的循环来解决相同的问题:

for line in $(cat $variable)
do
    docker-compose run backend echo $line
done