Powershell,反斜杠并向Docker发送命令

时间:2018-08-15 09:20:01

标签: powershell

这部分与Pass PowerShell variables to Docker commands有关,但是我有一个极端的案例需要解决,这可能是由于我缺乏PowerShell知识。

我有一个PowerShell脚本,可选地需要在-v命令中包含一个docker run选项。

这是脚本:

$pwd = (Get-Location)

# If GEM_HOME is declared, see if it is in the current directory. If not, we need
# to volume-mount it and change the variable value.
$gem_mount_cmd = ""
$gem_env_var = "-e GEM_HOME"
if (Test-Path env:GEM_HOME)
{
    $gem_home = $env:GEM_HOME
    $parent = (Split-Path -parent $gem_home)
    if ((Join-Path $parent '') -ne $pwd)
    {
        $gem_mount_cmd = "-v ""`$('$parent' -replace '\\','/'):/gems"""
        $gem_env_var = "-e GEM_HOME='/gems/"+(Split-Path -leaf $gem_home)+"'"
    }
}

$cmd = "& docker run --rm -it $gem_env_var $gem_mount_cmd -v ${pwd}:/srv alpine bash"
Write-Output $cmd
& $cmd

就目前而言,运行该脚本将导致PowerShell错误,导致docker run未被识别为cmdlet,函数,脚本文件或可运行程序的名称。

我也尝试过:

& docker run --rm -it $gem_env_var $gem_mount_cmd -v ${pwd}:/srv alpine bash

这给了我一个 Docker 错误,抱怨“未知的速记标志:-replace中的'r'”。

我还尝试将对$gem_mount_cmd的分配替换为:

$gem_mount_cmd = "-v $($parent -replace '\\','/'):/gems"

但是,这使我回到链接的问题的OP被击中的“来自守护程序的错误响应:无效模式”错误。

我还阅读了Powershell Call MSI with Arguments并将脚本修改为此:

$pwd = (Get-Location)

# If GEM_HOME is declared, see if it is in the current directory. If not, we need
# to volume-mount it and change the variable value.
$gem_mount_cmd = ""
$gem_env_var = "-e GEM_HOME"
if (Test-Path env:GEM_HOME)
{
    $gem_home = $env:GEM_HOME
    $parent = (Split-Path -parent $gem_home)
    if ((Join-Path $parent '') -ne $pwd)
    {
        $gem_mount_cmd = "-v $($parent -replace '\\','/'):/gems"
        $gem_env_var = "-e GEM_HOME='/gems/"+(Split-Path -leaf $gem_home)+"'"
    }
}

$params = 'run', '--rm', '-it',
          $gem_env_var, $gem_mount_cmd, '-v ${pwd}:/srv',
          'alpine', 'bash'
& docker @params

但这给了我同样的Docker“无效模式”错误。

要使它正常工作,我需要做什么?我想一个选择是让脚本嵌入docker run命令的两个不同版本,例如:

$pwd = (Get-Location)

# If GEM_HOME is declared, see if it is in the current directory. If not, we need
# to volume-mount it and change the variable value.
$gem_mount_cmd = ""
$gem_env_var = "-e GEM_HOME"
if (Test-Path env:GEM_HOME)
{
    $gem_home = $env:GEM_HOME
    $parent = (Split-Path -parent $gem_home)
    if ((Join-Path $parent '') -ne $pwd)
    {
        $gem_mount_cmd = "-v $($parent -replace '\\','/'):/gems"
        $gem_env_var = "-e GEM_HOME='/gems/"+(Split-Path -leaf $gem_home)+"'"
    }
}

if ("$gem_mount_cmd" -ne "") {
    & docker run --rm -it $gem_env_var -v "$($parent -replace '\\','/'):/gems" -v ${pwd}:/srv alpine bash
}
else {
    & docker run --rm -it -v ${pwd}:/srv alpine bash
}

但是感觉必须有更好的方法……

1 个答案:

答案 0 :(得分:1)

我将动态构建参数数组,然后将其放在命令中:

$params = 'run', '--rm', '--it'
if (Test-Path env:GEM_HOME) {
    $params += '-e', "GEM_HOME='/gems/$(Split-Path -Leaf $gem_home)'",
               '-v', "$($parent -replace '\\', '/'):/gems"
}
$params += '-v', "${pwd}:/srv", 'alpine', 'bash'

& 'docker.exe' @params