在“docker exec”命令中执行“bash -c”的操作

11

背景:我正在尝试为我的日常使用docker exec命令编写一个快捷方式。由于某些原因,当我在容器内使用bash控制台时,我的输出有时会出现问题(历史记录混乱,行覆盖等)。

我在这里阅读到这里的解决方法,可以通过在启动bash控制台之前添加一些命令来解决这个问题。


以下是我的脚本的相关摘录

#!/bin/bash
containerHash=$1
commandToRun='bash -c "stty cols $COLUMNS rows $LINES && bash -l"'

finalCommand="winpty docker exec -it $containerHash $commandToRun"
echo $finalCommand
$finalCommand

这是我得到的输出:

winpty docker exec -it 0b63a bash -c "stty cols $COLUMNS rows $LINES && bash -l"
cols: -c: line 0: unexpected EOF while looking for matching `"'
cols: -c: line 1: syntax error: unexpected end of file

我在这里看到,这与解析和扩展有关。然而,我不能使用一个函数或eval命令(或者至少我没有成功地使它工作)。

如果我直接在终端中执行第一行输出,它可以正常工作。

我该怎么解决这个问题?


1
一些提示可以在http://mywiki.wooledge.org/BashFAQ/050找到。 - Eric Renouf
@EricRenouf 谢谢!我在研究中已经偶然发现了这个,但似乎找不到适用于我的情况的段落...你看到有符合的吗?(也许是第三部分,但我不太理解) - AdrienW
1
你有没有考虑过最初的部分只是将参数存储在数组中而不是字符串中?另外,COLUMNSLINES是否可能包含意外的换行符或类似的内容?也许这些也应该加上引号? - Eric Renouf
我已经尝试将COLUMNSLINES替换为硬编码的值,但并没有帮助。你会将哪一部分作为数组来编写?如果我直接在终端中执行该命令,它可以正常运行,这是我不理解的地方。 - AdrienW
1个回答

9

这与Docker无关,而是Bash的问题(换句话说,命令中的docker部分正常工作,只是Bash在容器上发牢骚,就像它会在您的主机上一样):

最小可重现错误

cmd='bash -c "echo hello"'
$cmd

hello": -c: line 0: unexpected EOF while looking for matching `"'
hello": -c: line 1: syntax error: unexpected end of file

修复

cmd='bash -c "echo hello"'
eval $cmd

hello

Answer

foo='docker exec -it XXX bash -c "echo hello"'
eval $foo

这将让您在容器上执行命令 echo hello,现在如果您想向此命令添加动态变量(例如echo $string),您只需将单引号替换为双引号即可,为使其正常工作,您需要转义内部双引号:

foo="docker exec -it $container bash -c \"echo $variable\""

一个完整的例子

FOO="Hello"
container=$1
bar=$2

cmd="bash -c \"echo $FOO, $bar\""
final_cmd="docker exec -it $container $cmd"

echo "running command: \"$final_cmd\""
eval $final_cmd

让我们花些时间深入了解一下,
  • $FOO 是一个静态变量,在我们的情况下它的工作方式与普通变量完全相同,只不过是为了向您展示。
  • $bar 是一个动态变量,它将第二个命令行参数作为值。
  • 因为$cmd$final_cmd只使用双引号,所以变量被解释。
  • 由于我们使用eval $final_cmd命令进行解释,bash很高兴。

最后,以下是用法示例:

bash /tmp/dockerize.sh 5b02ab015730 world

提供
running command: "docker exec -it 5b02ab015730 bash -c "echo Hello, world""
Hello, world

我觉得我理解了。但是仍有一些困扰我的地方:使用这种解决方案,我必须在代码中硬编码变量:foo='winpty docker exec -it 0b63a bash -c "stty cols 255 rows 59 && bash -l"'。你知道在命令中漂亮地使用变量的方法吗?我可以将它们依次评估然后将整个东西粘合起来,但这感觉不太对。 - AdrienW
1
是的,让我修正我的回答。 - Arount

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