199

在 bash 中,与号 (&) 可用于在后台运行命令,并在命令完成运行之前将交互控制返回给用户。在 Powershell 中是否有等效的方法?

bash 中的用法示例:

 sleep 30 &
4

8 回答 8

157

只要命令是可执行文件或具有关联可执行文件的文件,请使用Start-Process(可从 v2 获得):

Start-Process -NoNewWindow ping google.com

您还可以将此作为功能添加到您的个人资料中:

function bg() {Start-Process -NoNewWindow @args}

然后调用变为:

bg ping google.com

在我看来,Start-Job 对于在后台运行进程的简单用例来说是一种过度杀伤:

  1. Start-Job 无权访问您现有的范围(因为它在单独的会话中运行)。您不能执行“Start-Job {notepad $myfile}”
  2. Start-Job 不保留当前目录(因为它在单独的会话中运行)。您不能在 myfile.txt 位于当前目录中的情况下执行“Start-Job {notepad myfile.txt}”。
  3. 输出不会自动显示。您需要以作业 ID 作为参数运行 Receive-Job。

注意:关于您的初始示例,“bg sleep 30”将不起作用,因为 sleep 是 Powershell 命令行开关。Start-Process 仅在您实际分叉一个进程时才有效。

于 2012-12-05T17:48:33.290 回答
41

从 PowerShell Core 6.0 开始,您可以&在命令结束时进行编写,这相当于在当前工作目录的后台运行您的管道。

它不等同&于 bash,它只是当前 PowerShell作业功能的一种更好的语法。它返回一个作业对象,因此您可以使用您将用于作业的所有其他命令。例如Receive-Job

C:\utils> ping google.com &

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
35     Job35           BackgroundJob   Running       True            localhost            Microsoft.PowerShell.M...


C:\utils> Receive-Job 35

Pinging google.com [172.217.16.14] with 32 bytes of data:
Reply from 172.217.16.14: bytes=32 time=11ms TTL=55
Reply from 172.217.16.14: bytes=32 time=11ms TTL=55
Reply from 172.217.16.14: bytes=32 time=10ms TTL=55
Reply from 172.217.16.14: bytes=32 time=10ms TTL=55

Ping statistics for 172.217.16.14:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 10ms, Maximum = 11ms, Average = 10ms
C:\utils>

如果你想在后台执行几个语句,你可以结合&调用运算符{ }脚本块和这个新的&后台运算符,如下所示:

& { cd .\SomeDir\; .\SomeLongRunningOperation.bat; cd ..; } &

以下是来自文档页面的更多信息:

来自PowerShell Core 6.0 中的新增功能

支持使用&符号 (&) 对管道进行后台处理 (#3360)

放在&管道的末尾会导致管道作为 PowerShell 作业运行。当管道在后台运行时,将返回一个作业对象。一旦管道作为作业运行,所有标准*-Jobcmdlet 都可用于管理作业。管道中使用的变量(忽略特定于流程的变量)会自动复制到作业中,因此Copy-Item $foo $bar &可以正常工作。该作业也在当前目录而不是用户的主目录中运行。有关 PowerShell 作业的详细信息,请参阅about_Jobs

来自about_operators / & 号背景运算符 &

& 后台运算符 &

在 PowerShell 作业中运行管道之前的管道。& 号后台操作符的行为类似于 UNIX“& 号操作符”,后者以后台进程的形式运行之前的命令。& 号后台运算符构建在 PowerShell 作业之上,因此它与Start-Job. 以下命令包含 & 后台运算符的基本用法。

Get-Process -Name pwsh &

这在功能上等同于Start-Job.

Start-Job -ScriptBlock {Get-Process -Name pwsh}

由于它在功能上等同于 using Start-Job,因此 & 号背景运算符返回一个Job对象,就像Start-Job does. 这意味着您可以使用Receive-JobRemove-Job就像您曾经Start-Job开始工作时一样。

$job = Get-Process -Name pwsh &
Receive-Job $job

输出

NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
------    -----      -----     ------      --  -- -----------
    0     0.00     221.16      25.90    6988 988 pwsh
    0     0.00     140.12      29.87   14845 845 pwsh
    0     0.00      85.51       0.91   19639 988 pwsh


$job = Get-Process -Name pwsh &
Remove-Job $job

有关 PowerShell 作业的详细信息,请参阅about_Jobs

于 2018-12-22T00:18:40.473 回答
31

似乎传递给的脚本块Start-Job未使用与命令相同的当前目录Start-Job执行,因此请确保在需要时指定完全限定的路径。

例如:

Start-Job { C:\absolute\path\to\command.exe --afileparameter C:\absolute\path\to\file.txt }
于 2012-07-07T06:19:39.210 回答
23
ps2> start-job {start-sleep 20}

我还没有弄清楚如何实时获取标准输出,开始工作需要你用 get-job 轮询标准输出

更新:我无法开始工作来轻松地做我想做的事,这基本上是 bash & 运算符。到目前为止,这是我最好的 hack

PS> notepad $profile #edit init script -- added these lines
function beep { write-host `a }
function ajp { start powershell {ant java-platform|out-null;beep} } #new window, stderr only, beep when done
function acjp { start powershell {ant clean java-platform|out-null;beep} }
PS> . $profile #re-load profile script
PS> ajp
于 2011-06-23T19:42:38.747 回答
22

您可以使用 PowerShell 作业 cmdlet 来实现您的目标。

PowerShell 中有 6 个与作业相关的 cmdlet。

  • 找工作
    • 获取在当前会话中运行的 Windows PowerShell 后台作业
  • 接收工作
    • 获取当前会话中 Windows PowerShell 后台作业的结果
  • 删除作业
    • 删除 Windows PowerShell 后台作业
  • 开始工作
    • 启动 Windows PowerShell 后台作业
  • 停工
    • 停止 Windows PowerShell 后台作业
  • 等待工作
    • 禁止命令提示符,直到会话中运行的一个或所有 Windows PowerShell 后台作业完成

如果对此感兴趣,您可以下载示例如何在 PowerShell 中创建后台作业

于 2016-11-09T09:13:38.547 回答
6

你可以做这样的事情。

$a = start-process -NoNewWindow powershell {timeout 10; 'done'} -PassThru

如果你想等待它:

$a | wait-process

奖励 osx 或 linux 版本:

$a = start-process pwsh '-c',{start-sleep 5; 'done'} -PassThru 

我有示例 pinger 脚本。args 作为数组传递:

$1 = start -n powershell pinger,comp001 -pa
于 2019-07-10T03:32:02.583 回答
4

tl;博士

Start-Process powershell { sleep 30 }
于 2019-09-05T15:09:19.523 回答
-1

我已经在 PowerShell v1.0 中成功使用了这里描述的解决方案http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!130.entry 。在 PowerShell v2.0 中肯定会更容易。

于 2008-10-09T10:55:04.697 回答