【问题标题】:Powershell Docker Command Doesn't Work Like Bat FilePowershell Docker 命令不像 Bat 文件那样工作
【发布时间】:2022-03-20 18:52:54
【问题描述】:

我正在尝试创建一个脚本来启动一个 docker 容器并安装一个名称中包含空格的本地文件夹。当我使用 docker run 命令运行 *.bat 文件时,我可以让它正常工作:

docker run -p 8081:8081 -v "C:\Test Folder With Blanks":/zzz myimage jupyter lab --notebook-dir=/zzz--ip=0.0.0.0 --port=8081 --allow-root

但是当我尝试在 Powershell 脚本文件中执行相同操作时,我收到错误:

$CMD = 'docker run -p 8081:8081 -v "C:\Test Folder With Blanks":/zzz myimage jupyter lab --notebook-dir=/zzz--ip=0.0.0.0 --port=8081 --allow-root'
    
Invoke-Expression $CMD
docker: invalid reference format.
See 'docker run --help'.

我在 Win10 上并在 Visual Studio Code IDE 中运行 Powershell。

感谢您的想法。

【问题讨论】:

    标签: docker powershell batch-file


    【解决方案1】:

    首先,强制性警告:除非您将命令行存储为单个字符串某处并且完全控制或信任字符串的内容,Invoke-Expression should generally be avoided


    您发现 PowerShell 如何处理由直接连接的带引号和不带引号的部分组成的复合标记不一致

    具体来说,参数 "C:\Test Folder With Blanks":/zzz 意外地分成两部分(即,作为两个单独的参数传递)。

    解决方法引用整个参数,即
    "C:\Test Folder With Blanks:/zzz"

    注意:我假设 docker 实际上并不需要在其参数中引用 部分,这是不应该的;但是,Windows 上有一些备受瞩目的 CLI,尤其是 msiexec

    或者,使用包含在(...) 中的表达式 来组成您的字符串;例如
    ("C:\Test Folder With Blanks" + ':/zzz')

    在这种情况下没有充分的理由这样做,但如果您需要在字符串的一部分 ("...") 而在另一部分 ('...') 中不需要字符串插值,这可能会有所帮助。

    一般注意事项

    • cmd.exe 以及与 POSIX 兼容的 shell(例如 bash)相比,PowerShell 有几个附加元字符,尤其是 @987654337 @(在令牌的开头)、{ / };。因此,您不能总是期望为这些 shell 编写的命令行在 PowerShell 中按原样工作

    • 从 PowerShell 7.2.2 开始,将参数传递给 外部程序(例如 docker)对于具有 嵌入 " 字符的参数而言从根本上被破坏了和 空字符串 参数 - 请参阅 this answer


    从 PowerShell 7.2.2 开始,不一致的一般模式如下:

    如果是参数:

    • 一个引用标记开头 - 无论是单引号 ('...') 还是双引号 ("...") -
    • and 在结束引号之后有其他字符,

    第一个这样的字符开始一个单独的参数

    例如"foo":bar / "foo"=bar / "foo"'bar' 分别作为单独的参数传递 foo:bar / foo=bar / foobar

    换句话说:

    • 如果第一个标记被引用,则您不能混合使用带引号和不带引号/不同引号的标记来组合单个字符串参数。

    • 相反,如果第一个标记未引用,它确实工作,包括未引用的简单变量引用,例如$HOME

    # OK: First token is unquoted.
    PS> cmd /c echo foo"bar"'baz'last
    foobarbazlast
    
    # !! BROKEN: First token is quoted.
    # !!         Because each successive token is quoted too, 
    # !!         each becomes its own argument.
    PS> cmd /c echo 'foo'"bar"'baz'last
    foo bar baz last
    

    GitHub issue #6467 讨论了这种不一致;但是,它已被关闭,因为令人惊讶的是,这种行为是经过设计考虑的。


    如果第一个标记未引用,这不会发生;但是,有相关错误未引用标记开头,类似地将参数分成两部分,这与它们看起来像命名参数 到 PowerShell(这是一个 PowerShell 概念,在调用外部程序时不适用):

    【讨论】:

      猜你喜欢
      • 2013-04-12
      • 2018-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-21
      相关资源
      最近更新 更多