Powershell相当于bash&符(&),用于派生/运行后台进程


157

在bash中,“&”号可用于在后台运行命令,并在命令完成运行之前将交互式控件返回给用户。在Powershell中有等效的方法吗?

在bash中的用法示例:

 sleep 30 &

Answers:


123

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

Start-Process -NoNewWindow ping google.com

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

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

然后调用变为:

bg ping google.com

我认为,对于在后台运行流程的简单用例而言,Start-Job是一个过分的矫正:

  1. Start-Job无权访问您现有的范围(因为它在单独的会话中运行)。您无法执行“开始工作{notepad $ myfile}”
  2. Start-Job不会保留当前目录(因为它在单独的会话中运行)。如果myfile.txt在当前目录中,则无法执行“开始作业{notepad myfile.txt}”。
  3. 输出不会自动显示。您需要使用作业的ID作为参数来运行Receive-Job。

注意:关于您的第一个示例,“ bg sleep 30”将不起作用,因为睡眠是Powershell Commandlet。仅当您真正分叉一个进程时,启动进程才起作用。


7
很高兴我找到了这个答案。我正在寻找与Unix两次分叉机制相同的机制。在我看来,Start-Job当PS shell退出时,某些开头的内容将被杀死。相反,Start-Process在PS shell退出后,似乎始于某种东西的东西将继续运行。这是一个主要区别。
peterh

是的-如果您使用来启动脚本Start-Process,它将在shell终止后继续存在,但是,如果您从控制台窗口启动该脚本,则它将始终绑定到该窗口,并且关闭该窗口将终止该进程。
2015年

1
但是请注意,您不能使用进行输出重定向,Start-Process因此这将不起作用:Start-Process {ping -n 1000 example.com > ping__example.com.txt }。同样的方法也可以Start-Job正常工作(尽管您必须使用输出文件的完整路径)。
Nux

1
尝试执行此操作以运行节点Web服务器,并且在退出Powershell时该过程终止。有人知道为什么吗?
Jel

@杰尔不,但古斯的评论谈到了这一点。
jpaugh

26

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

例如:

Start-Job { C:\absolute\path\to\command.exe --afileparameter C:\absolute\path\to\file.txt }

3
因此,例如,如果需要在命令行中运行Git Pull,则需要指定所有内容的完整路径...?真烦人。
CMCDragonkai 2014年

1
谢谢,很好的提示,一直忙着无法完成的工作,这就是原因。
2015年

@CMCDragonkai或只执行Start-Job {cd C:\ Path \ To \ Repo; git pull}
Mahomedalid

21
ps2> start-job {start-sleep 20}

我尚未弄清楚如何实时获取stdout,start-job要求您使用get-job轮询stdout

更新:我不能开始工作轻松地做我想要的,基本上是bash&运算符。到目前为止,这是我最好的技巧

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

1
从PowerShell v3.0开始,您可以像这样实时获取stdout:Start-Job { Write-Output 'Hello world' } | Receive-Job -Wait
JamesQMurphy 2014年

19

在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}

由于在功能上等同于使用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


1
感谢您的出色总结,因为100毫秒的MS页面无法完成。
not2qubit

知道如何处理控制台作业吗?我尝试使用进行上述操作Receive-Job 3,但没有任何反应。
not2qubit

@ not2qubit我不确定“ 控制台作业” 是什么意思。您要在后台运行什么命令?
Mariusz Pawelski,

我当时使用的是一个启动Windows控制台的应用程序,但我无法获得任何输出,希望能像将nix的世界fg带到* foreground一样获得它。
not2qubit

@ not2qubit不幸的是,fg在powershell中似乎没有与Unix类似的东西:(我记得在找它,但找不到任何东西
Mariusz Pawelski,

17

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

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

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

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


1
很好的答案,因为它涉及Powershell 3+。job cmdlet和以前的答案有什么区别?
Jeremy Hajek

3

你可以做这样的事情。

$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

start 将派生该过程并将控制权返回给调用者。更多信息在这里
Aethalides '19

@Aethalides start实际上是powershell中启动过程的别名。
js2010


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.