Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 将命令组直接导入“docker exec”`_Bash_Docker_Docker Exec - Fatal编程技术网

Bash 将命令组直接导入“docker exec”`

Bash 将命令组直接导入“docker exec”`,bash,docker,docker-exec,Bash,Docker,Docker Exec,我有以下命令,该命令工作正常,并在返回前打印foo: docker exec-i/bin/sh

我有以下命令,该命令工作正常,并在返回前打印
foo

docker exec-i/bin/sh
我想用一个管道将多个命令导入容器,例如
echo'foo'
ls/
。我尝试了以下方法:

  • 此操作失败,因为它在主机上运行命令,并将输出通过管道传输到容器中:
    {
    回声“foo”
    ls/
    }|码头执行官-i/bin/sh
    
  • 这会失败,因为它的语法不正确。它也在主机上运行:

    {
    回声“foo”
    ls/
    }|码头执行官-i/bin/sh
    
  • 此操作失败,但我不想使用字符串数组:

    “echo”foo“'ls/”中的命令的
    
    做
    docker exec-i/bin/sh
  • 我还尝试过其他几种方法,比如将命令管道化到
    tee
    echo
    中,但都没有成功。如果你想知道我为什么要做这件看似荒谬的事,那是因为:

    • 这是一个简短的脚本,我想保留在一个地方
    • 我想使用语法高亮显示,所以我不想将其全部存储在字符串列表中
    • 容器中有脚本应该运行的程序,而主机没有
    • 这是一个自动过程,我想在主机上用crontab触发它

    您可以按以下方式运行一组命令

     docker exec -i <id> /bin/sh -c 'echo "foo"; ls -l'
    

    docker exec -i 996eee5d121d /bin/sh -c 'echo 'foo'; ls -l'
    
    docker exec -i 996eee5d121d /bin/sh -c 'echo foo; ls -l'
    
    如果要运行2个以上的命令,只需附加
    在每个命令之后,如

    docker exec -i 996eee5d121d /bin/sh -c 'echo "foo"; ls -l; ls -a'
    
    我找到了一个解释如何将命令导入
    docker exec

    echo“echo foo”| docker exec-i/bin/sh-
    
    现在我们需要一种通过管道传输多个命令的方法。命令组无法工作,因为它们在主机上运行,分号分隔的命令可能会变得混乱。我想写一个函数,然后得到它的主体,结果证明你可以用一个简单的

    您可以将所有这些部分组合起来,将命令导入容器:

    函数func{
    回声“foo”
    ls/
    }
    声明-f func | sed'1,2d$d'| docker exec-i/bin/bash-
    
    语法高亮显示仍然可以在函数中工作,并且易于阅读

    如果要使用容器中主机上的环境变量,必须在docker exec中手动列出它们,如下所示:

    …|docker exec-i-e VAR=$VAR/bin/bash-
    
    编辑:我将此作为一个可能的解决方案留在这里,但公认的答案是我正在使用的正确解决方案。

    使用此处文档

    docker run -i --rm alpine /bin/sh <<EOF
    echo abc
    ls /
    EOF
    
    执行:

    $ bash -x ./script.sh
    + tail -n+5 ./script.sh
    + docker run -i --rm alpine /bin/sh -x
    + echo abc
    + ls /
    abc
    bin
    ...
    var
    + exit
    

    以类似的方式,您可以使用
    sed
    或其他解析工具来提取某些标记之间的唯一相关部分。例如,

    您可以将其写入shell脚本并
    将其复制到图像中,这样您就不必处理shell转义了吗?更好的方法是,将其设置为独立容器的
    CMD
    。@DavidMaze我不喜欢第一个解决方案,因为我希望能够调整此脚本,而无需重建目标容器。不过,第二种解决方案可能会起作用,它可以通过容器的名称直接连接到容器,而不依赖容器的id。
    此解决方案失败,但我还是不想使用字符串数组:
    请显示什么是“字符串数组”您可能想使用@KamilCuk该示例命令正在字符串数组上循环,并将其分配给
    命令
    变量。数组可能不是正确的术语,但它仍在一个列表上迭代。很抱歉,这对于几个短命令非常有用,但在尝试使用更多命令时变得不可管理,因此建议您使用shell脚本并运行
    'echo'foo';ls-l'
    很奇怪-
    foo
    没有被引用。同样的方式,你可以
    “echo”“foo”;“ls'-l'
    这就是我要找的!语法突出显示在herdoc中不起作用,这很遗憾,但它看起来确实起作用了,而且看起来是解决我的问题的正确方法。当然可以。但是以
    #
    开头的行是注释,所以没有必要删除它们。我删除了我的旧注释。我可以使用
    sed
    获取模式之间的内容,方法如下:
    sed-n/^#####脚本开始###/,/^###脚本结束###/p“$0”
    docker exec -i <id> /bin/sh < <(echo "echo 'foo'")
    
    docker exec -i <id> /bin/sh <<<"echo 'foo'"
    
    #!/bin/sh
    # output this script except first 4 lines to docker
    tail -n+5 "$0" | docker run -i --rm alpine /bin/sh -x
    exit  # we exit original script
    #!/bin/sh
    # inside docker now
    echo abc
    ls /
    
    $ bash -x ./script.sh
    + tail -n+5 ./script.sh
    + docker run -i --rm alpine /bin/sh -x
    + echo abc
    + ls /
    abc
    bin
    ...
    var
    + exit