运行 docker 在 Powershell 后台

Run docker in background under Powershell

简单的问题,我想在后台执行运行 docker命令。
(实际上 运行 在 Powershell 下使用命令行参数执行任何命令是我真正的问题,但是 docker 是一个简单的具体问题)

我有一个命令

docker run -ti --rm -e DISPLAY=$DISPLAY firefox

运行在 Powershell 下没问题,但会阻塞。

我想运行使用 *nix:

下执行“&”的等效方法
docker run -ti --rm -e DISPLAY=$DISPLAY firefox &

我试过了

但都不适合我:

> ping google.com &
At line:1 char:17
+ ping google.com &
+                 ~
The ampersand (&) character is not allowed.

> Start-Process "C:\Program Files\Docker\Docker\resources\bin\docker.exe" run -ti --rm -e DISPLAY=$DISPLAY firefox
Start-Process : Parameter cannot be processed because the parameter name 'e' is ambiguous. Possible
matches include: -ErrorAction -ErrorVariable.
At line:1 char:86
+ ... Files\Docker\Docker\resources\bin\docker.exe" run -ti --rm -e DISPLAY ...
+                                                                ~~
    + CategoryInfo          : InvalidArgument: (:) [Start-Process], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameter,Microsoft.PowerShell.Commands.StartProcessCommand

试图将整个命令包装在 Start-Process { ... } 中也不起作用。

[UPDATE/Summary]

接受的答案有效(在我从命令行中删除“-ti”之后),正如@nischay goyal 所说,"please don't use -it as it opens the terminal and blocks it."。我得到的错误是:

the input device is not a TTY.  If you are using mintty, try prefixing the command with 'winpty'
    + CategoryInfo          : NotSpecified: (the input devic...d with 'winpty':String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
    + PSComputerName        : localhost

总而言之,解决问题的方法有很多种。选择一个适合你的。

firefox 命令不需要任何标准输入,也不需要 tty。所以删除 -it。接下来添加代表分离模式的 -d,docker 内部 运行 守护进程的标准方式,或其他非交互式命令。

docker run -d --rm -e DISPLAY=$DISPLAY firefox

要完全执行 docker 中的命令并在后台使用 docker,您可以使用:

docker run $YourOption $ImageDocker exec $yourCommand 

并且不要使用 -i -t 选项,它会打开终端

做类似的事情

docker run --rm -e DISPLAY=$DISPLAY firefox exec "ping google.com"

对于运行处于分离模式的docker容器,请不要使用-it,因为它会打开终端并阻止它。

docker run --rm -e DISPLAY=$DISPLAY firefox

对于 运行在 PowerShell 中在后台运行命令,只要命令是可执行文件或具有关联可执行文件的文件,请使用 Start-Process(可从 v2 获得):

Start-Process -NoNewWindow ping google.com

在 PowerShell 后台使用 Start-Job 到 运行 命令。

在 PowerShell [Core] 6+ 中,您还可以将 & 放在命令的末尾,就像在 POSIX-like shell 中一样,例如Bash.

在这两种情况下,都会返回一个作业对象 (System.Management.Automation.PSRemotingJob),您可以使用各种 *-Job cmdlet 进行管理 - 请参阅 about_Jobs.

PowerShell 中的作业与 POSIX 类 shell 中的作业相似(例如 Bash) ,但存在一些 根本差异,特别是 inability 运行 interactive 命令背景 - 见 this comment on GitHub.

后台作业使用 子进程,它 运行 是后台隐藏的 PowerShell 实例,速度慢且资源密集。

因此考虑基于线程Start-ThreadJob cmdlet as a faster and more light-weight alternative - see .

语法也适用于 6 以下的 PowerShell 版本,Start-Job:

# Preferable alternative: Start-ThreadJob
$job = Start-Job { docker run --rm -e DISPLAY=$using:DISPLAY firefox }

注:-ti被删除,因为,如Nischay Goyal points out, it would open an interactive shell session, which means that the call wouldn't return until that session is manually closed. However, not that Start-Job generally doesn't support running interactive programs in the background, as explained here.

注意需要通过 $using: 范围说明符在调用方范围内引用 $DISPLAY 变量 - 参见 about_Remote_Variables.

警告:在 6.x 之前的 PowerShell 版本中,以这种方式启动的后台作业使用与调用者无关的 固定 工作目录 - 请参阅

PowerShell [Core] 6+ 备选方案:将 & 放在命令末尾:

$job = docker run --rm -e DISPLAY=$DISPLAY firefox &

请注意,您 不需要 使用此语法的 $using: 范围说明符,即使在 PowerShell 6.x 中,该作业也会看到相同的工作目录来电者。

请注意,没有类似的简洁语法来创建 thread 作业(相当于 Start-ThreadJob 调用),但从 PowerShell 7.0 开始,但加一是this feature request on GitHub的主题。


如上所述,您可以使用其他各种 *-Job cmdlet 管理 作业 一旦创建(它们还管理使用 Start-ThreadJob 创建的线程作业);例如,以下命令同步等待作业完成,打印其输出,然后删除作业。

$job | Receive-Job -Wait -AutoRemoveJob

至于你试过的

ping google.com & 中的后置 & 不起作用,因为您 运行 正在使用 Windows PowerShell (PowerShell 版本高达 v5.1),而此语法需要 PowerShell [Core] 版本 6 或更高版本。

Start-Process 旨在异步启动可执行文件,默认情况下在新的 window 中(在 Windows 上)。
它主要用于在新控制台 window.

中启动 GUI 应用程序(异步)或 运行ning shell 命令

虽然它也可以不可见地启动进程,但您几乎无法控制该进程,并且只能通过文本文件间接捕获其输出。

您的调用失败的原因是您试图将直通参数直接传递给Start-Process,而不是将它们传递给-ArgumentList参数(作为单个字符串,在最简单的情况下)。