Powershell-Äquivalent zu Bash-kaufmännischem Und (&) zum Verzweigen / Ausführen von Hintergrundprozessen

157

In bash kann das kaufmännische Und (&) verwendet werden, um einen Befehl im Hintergrund auszuführen und die interaktive Steuerung an den Benutzer zurückzugeben, bevor der Befehl ausgeführt wurde. Gibt es eine äquivalente Methode, um dies in Powershell zu tun?

Anwendungsbeispiel in Bash:

 sleep 30 &
eddiegroves
quelle

Antworten:

123

Verwenden Sie Start-Process (verfügbar ab Version 2), solange der Befehl eine ausführbare Datei oder eine Datei ist, der eine ausführbare Datei zugeordnet ist :

Start-Process -NoNewWindow ping google.com

Sie können dies auch als Funktion in Ihr Profil einfügen:

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

und dann wird der Aufruf:

bg ping google.com

Meiner Meinung nach ist Start-Job ein Overkill für den einfachen Anwendungsfall, einen Prozess im Hintergrund auszuführen:

  1. Start-Job hat keinen Zugriff auf Ihren vorhandenen Bereich (da er in einer separaten Sitzung ausgeführt wird). Sie können "Start-Job {notepad $ myfile}" nicht ausführen.
  2. Start-Job behält das aktuelle Verzeichnis nicht bei (da es in einer separaten Sitzung ausgeführt wird). Sie können "Start-Job {notepad myfile.txt}" nicht ausführen, wenn sich myfile.txt im aktuellen Verzeichnis befindet.
  3. Die Ausgabe wird nicht automatisch angezeigt. Sie müssen Receive-Job mit der ID des Jobs als Parameter ausführen.

HINWEIS: In Bezug auf Ihr erstes Beispiel würde "bg sleep 30" nicht funktionieren, da sleep ein Powershell-Commandlet ist. Start-Prozess funktioniert nur, wenn Sie tatsächlich einen Prozess verzweigen.

Bogdan Calmac
quelle
7
Ich bin froh, dass ich diese Antwort gefunden habe. Ich suchte nach dem Äquivalent eines Unix-Doppelgabelmechanismus. Mir scheint, dass etwas, mit dem angefangen wurde Start-Job, getötet wird, wenn die PS-Shell beendet wird. Im Gegensatz dazu scheint etwas, mit dem begonnen wurde Start-Process, nach dem Beenden der PS-Shell weiter zu laufen. Dies ist ein großer Unterschied.
Peterh
Ja - wenn Sie ein Skript mit starten Start-Process, überlebt es die Shell-Beendigung. Wenn Sie es jedoch über ein Konsolenfenster gestartet haben, bleibt es an dieses Fenster gebunden, und das Schließen des Fensters beendet den Prozess.
Guss
1
Beachten Sie jedoch, dass Sie keine Ausgabeumleitung mit durchführen können Start-Processund dies daher NICHT funktioniert : Start-Process {ping -n 1000 example.com > ping__example.com.txt }. Das Gleiche gilt für Start-Jobfunktioniert einwandfrei (obwohl Sie den vollständigen Pfad zur Ausgabedatei verwenden müssen).
Nux
1
Es wurde versucht, dies zu tun, um einen Knoten-Webserver auszuführen, und der Prozess wird beendet, wenn ich Powershell beende. Weiß jemand warum?
Jel
@ Jel Nein, aber Guss 'Kommentar spricht darüber.
Jpaugh
26

Es scheint, dass der übergebene Skriptblock Start-Jobnicht mit demselben aktuellen Verzeichnis wie der Start-JobBefehl ausgeführt wird. Geben Sie daher bei Bedarf den vollständig qualifizierten Pfad an.

Beispielsweise:

Start-Job { C:\absolute\path\to\command.exe --afileparameter C:\absolute\path\to\file.txt }
Gian Marco
quelle
3
Wenn ich beispielsweise Git Pull in der Befehlszeile ausführen muss, muss ich den vollständigen Pfad zu allem angeben ...? Das ist wirklich nervig.
CMCDragonkai
1
danke, toller tipp, habe einen job gemacht, der nicht laufen würde, das war der grund warum.
Omni
@CMCDragonkai oder Sie können einfach Start-Job {cd C: \ Path \ To \ Repo; Git Pull}
Mahomedalid
21
ps2> start-job {start-sleep 20}

Ich habe noch nicht herausgefunden, wie man stdout in Echtzeit bekommt. Für den Startjob müssen Sie stdout mit get-job abfragen

Update: Ich konnte den Job nicht starten, um einfach zu tun, was ich will, was im Grunde die Bash & Operator ist. Hier ist mein bisher bester 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
Dustin Getz
quelle
1
Ab PowerShell v3.0 können Sie in Echtzeit wie folgt stdout erhalten:Start-Job { Write-Output 'Hello world' } | Receive-Job -Wait
JamesQMurphy
19

Ab PowerShell Core 6.0 können Sie &am Ende des Befehls schreiben. Dies entspricht der Ausführung Ihrer Pipeline im Hintergrund im aktuellen Arbeitsverzeichnis .

Es ist nicht gleichbedeutend mit &in bash, es ist nur eine schönere Syntax für die aktuelle PowerShell- Jobfunktion . Es gibt ein Jobobjekt zurück, sodass Sie alle anderen Befehle verwenden können, die Sie für Jobs verwenden würden. Zum Beispiel 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>

Wenn Sie einige Aussagen im Hintergrund ausführen möchten , können Sie kombinieren &Call - Betreiber , { }Script - Block und diesen neuen &Hintergrund Operator wie hier:

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

Hier einige weitere Informationen von den Dokumentationsseiten:

von den Neuerungen in PowerShell Core 6.0 :

Unterstützung des Hintergrunds von Pipelines mit kaufmännischem Und (&) (# 3360)

Wenn Sie &am Ende einer Pipeline einfügen, wird die Pipeline als PowerShell-Job ausgeführt. Wenn eine Pipeline im Hintergrund ist, wird ein Jobobjekt zurückgegeben. Sobald die Pipeline als Job ausgeführt wird, können alle Standard- *-JobCmdlets zum Verwalten des Jobs verwendet werden. In der Pipeline verwendete Variablen (die prozessspezifische Variablen ignorieren) werden automatisch in den Job kopiert, sodass sie Copy-Item $foo $bar &einfach funktionieren. Der Job wird auch im aktuellen Verzeichnis anstelle des Basisverzeichnisses des Benutzers ausgeführt. Weitere Informationen zu PowerShell-Jobs finden Sie unter about_Jobs .

von about_operators / Ampersand Hintergrundoperator & :

Kaufmännisches Und-Hintergrund-Operator &

Führt die Pipeline zuvor in einem PowerShell-Job aus. Der kaufmännische Und-Hintergrundoperator verhält sich ähnlich wie der UNIX-kaufmännische Und-Operator, der den Befehl vor ihm als Hintergrundprozess ausführt. Der kaufmännische Und-Hintergrund-Operator basiert auf PowerShell-Jobs, sodass er viele Funktionen gemeinsam nutzt Start-Job. Der folgende Befehl enthält die grundlegende Verwendung des kaufmännischen Und-Hintergrundoperators.

Get-Process -Name pwsh &

Dies entspricht funktional der folgenden Verwendung von Start-Job.

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

Da dies funktional der Verwendung entspricht Start-Job, gibt der kaufmännische Und-Hintergrund-Operator ein JobObjekt wie folgt zurück Start-Job does. Dies bedeutet, dass Sie in der Lage sind, Receive-Jobund Remove-Jobgenau so, wie Sie es tun würden, wenn Sie Start-Jobden Job gestartet hätten.

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

Ausgabe

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

Weitere Informationen zu PowerShell-Jobs finden Sie unter about_Jobs .

Mariusz Pawelski
quelle
1
Vielen Dank für diese großartige Zusammenfassung, die Hunderte von MS-Seiten nicht erreichen konnten.
not2qubit
Irgendeine Idee, wie man mit Konsolenjobs umgeht? Ich habe das oben versucht mit Receive-Job 3, aber nichts passiert.
not2qubit
@ not2qubit Ich bin mir nicht sicher, was du mit " Konsolenjobs " meinst . Welchen Befehl führen Sie aus, den Sie im Hintergrund ausführen möchten?
Mariusz Pawelski
Ich habe eine App verwendet, die eine Windows-Konsole startet, aber ich kann keine Ausgabe erhalten und hatte gehofft, sie ähnlich wie in der Nix-Welt fgzu erhalten, um den Job in den Vordergrund zu rücken .
not2qubit
@ not2qubit Leider scheint es fgin Powershell kein ähnliches Unix zu geben :( Ich erinnere mich, dass ich danach gesucht habe, aber nichts gefunden habe
Mariusz Pawelski
17

Sie können PowerShell-Job-Cmdlets verwenden, um Ihre Ziele zu erreichen.

In PowerShell sind 6 auftragsbezogene Cmdlets verfügbar.

  • Arbeit bekommen
    • Ruft Windows PowerShell-Hintergrundjobs ab, die in der aktuellen Sitzung ausgeführt werden
  • Job empfangen
    • Ruft die Ergebnisse der Windows PowerShell-Hintergrundjobs in der aktuellen Sitzung ab
  • Job entfernen
    • Löscht einen Windows PowerShell-Hintergrundjob
  • Start-Job
    • Startet einen Windows PowerShell-Hintergrundjob
  • Stop-Job
    • Stoppt einen Windows PowerShell-Hintergrundjob
  • Wait-Job
    • Unterdrückt die Eingabeaufforderung, bis einer oder alle in der Sitzung ausgeführten Windows PowerShell-Hintergrundjobs abgeschlossen sind

Wenn Sie daran interessiert sind, können Sie das Beispiel zum Erstellen eines Hintergrundjobs in PowerShell herunterladen

Eric
quelle
1
Gute Antwort, da es sich um Powershell 3+ handelt. Was ist der Unterschied zwischen Job-Cmdlets und den vorherigen Antworten?
Jeremy Hajek
3

Sie können so etwas tun.

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

Und wenn Sie darauf warten möchten:

$a | wait-process

Bonus OSX oder Linux Version:

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

Beispiel Pinger Skript, das ich habe. Die Argumente werden als Array übergeben:

$1 = start -n powershell pinger,comp001 -pa
js2010
quelle
start wird den Prozess verzweigen und die Kontrolle an den Anrufer zurückgeben. Weitere Infos hier
Aethalides
@Aethalides start ist eigentlich ein Alias ​​für den Startprozess in Powershell.
js2010
2

tl; dr

Start-Process powershell { sleep 30 }
Bence des Weltraums
quelle