バックグラウンドプロセスのフォーク/実行用のbashアンパサンド(&)に相当するPowershell


157

bashでは、アンパサンド(&)を使用してコマンドをバックグラウンドで実行し、コマンドの実行が完了する前にインタラクティブな制御をユーザーに返すことができます。Powershellでこれを行う同等の方法はありますか?

bashでの使用例:

 sleep 30 &

回答:


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は既存のスコープにアクセスできません(別のセッションで実行されるため)。「Start-Job {notepad $ myfile}」は実行できません
  2. Start-Jobは現在のディレクトリを保持しません(別のセッションで実行されるため)。myfile.txtが現在のディレクトリにある場合、「Start-Job {notepad myfile.txt}」は実行できません。
  3. 出力は自動的には表示されません。ジョブのIDをパラメーターとして使用して、Receive-Jobを実行する必要があります。

注:最初の例では、sleepはPowershellコマンドレットであるため、「bg sleep 30」は機能しません。Start-Processは、実際にプロセスをフォークした場合にのみ機能します。


7
この答えを見つけてよかった。私は、Unix fork-twiceメカニズムに相当するものを探していました。私にはStart-Job、PSシェルが終了すると、何かで始まるものが殺されるようです。対照的Start-Processに、PSシェルが終了した後、で開始されたものは引き続き実行されるようです。これは大きな違いです。
peterh 2013年

はい-を使用してスクリプトを開始するStart-Processと、シェルの終了後も存続しますが、コンソールウィンドウから開始した場合は、そのウィンドウにバインドされたままになり、ウィンドウを閉じるとプロセスが終了します。
Guss

1
ただし、では出力リダイレクトを実行できないStart-Processため、これは機能しませんStart-Process {ping -n 1000 example.com > ping__example.com.txt }。同じことがStart-Jobうまく機能します(ただし、出力ファイルへのフルパスを使用する必要があります)。
Nux

1
これを実行してノードのWebサーバーを実行しようとしましたが、Powershellを終了するとプロセスが終了します。誰もが理由を知っていますか?
Jel

@ジェルいいえ、しかしGussのコメントはそれについて話します。
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のとして、あなたは、このようにリアルタイムで標準出力を得ることができます:Start-Job { Write-Output 'Hello world' } | Receive-Job -Wait
JamesQMurphy

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>

いくつかのステートメントをバックグラウンドで実行する場合は、次の&ようにcallオペレーター{ }スクリプトブロック、およびこの新しい&バックグラウンドオペレーターを組み合わせることができます。

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

ドキュメントページからの詳細は次のとおりです。

PowerShell Core 6.0の新機能から:

アンパサンド(&)を使用したパイプラインのバックグラウンドのサポート(#3360)

&パイプラインの最後に置くと、パイプラインがPowerShellジョブとして実行されます。パイプラインがバックグラウンド化されると、ジョブオブジェクトが返されます。パイプラインがジョブとして実行されると、すべての標準*-Jobコマンドレットを使用してジョブを管理できます。パイプラインで使用される変数(プロセス固有の変数は無視)は自動的にジョブにコピーされるため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と同様にそれを取得したいと考えていました。
not2qubit

@ not2qubit残念ながらUNIXに類似なものが存在しないようですfg、私はそれを探して覚え:( PowerShellでは、しかし、何かを見つけることができませんでした
マリウシュPawelski

17

PowerShellジョブコマンドレットを使用して、目標を達成できます。

PowerShellでは、6つのジョブ関連のコマンドレットを使用できます。

  • Get-Job
    • 現在のセッションで実行されているWindows PowerShellバックグラウンドジョブを取得します
  • 受信ジョブ
    • 現在のセッションのWindows PowerShellバックグラウンドジョブの結果を取得します
  • 削除ジョブ
    • Windows PowerShellバックグラウンドジョブを削除します
  • 開始ジョブ
    • Windows PowerShellバックグラウンドジョブを開始します
  • ストップジョブ
    • Windows PowerShellバックグラウンドジョブを停止します
  • 待機ジョブ
    • セッションで実行されている1つまたはすべてのWindows PowerShellバックグラウンドジョブが完了するまで、コマンドプロンプトを抑制します。

それについて興味があれば、PowerShellでバックグラウンドジョブを作成する方法のサンプルをダウンロードできます。


1
Powershell 3以上を扱っているため、良い答えです。jobコマンドレットと以前の回答の違いは何ですか?
Jeremy Hajek 2017年

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スクリプトの例。引数は配列として渡されます:

$1 = start -n powershell pinger,comp001 -pa

start プロセスをフォークし、呼び出し元に制御を返します。詳細はこちら
Aethalides

@Aethalides startは、実際にはpowershellのstart-processのエイリアスです。
js2010


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.