Equivalente Powershell di e commerciale bash (&) per biforcazione / esecuzione di processi in background


158

In bash la e commerciale (&) può essere utilizzata per eseguire un comando in background e restituire all'utente il controllo interattivo prima che il comando abbia terminato l'esecuzione. Esiste un metodo equivalente per farlo in Powershell?

Esempio di utilizzo in bash:

 sleep 30 &

Risposte:


125

Finché il comando è un eseguibile o un file a cui è associato un eseguibile, utilizzare Start-Process (disponibile da v2):

Start-Process -NoNewWindow ping google.com

Puoi anche aggiungere questo come funzione nel tuo profilo:

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

e quindi l'invocazione diventa:

bg ping google.com

A mio avviso, Start-Job è un overkill per il semplice caso d'uso di eseguire un processo in background:

  1. Start-Job non ha accesso all'ambito esistente (poiché viene eseguito in una sessione separata). Non puoi fare "Start-Job {notepad $ myfile}"
  2. Start-Job non conserva la directory corrente (poiché viene eseguita in una sessione separata). Non è possibile eseguire "Start-Job {notepad myfile.txt}" dove myfile.txt si trova nella directory corrente.
  3. L'output non viene visualizzato automaticamente. È necessario eseguire Ricevi-Lavoro con l'ID del lavoro come parametro.

NOTA: per quanto riguarda il tuo esempio iniziale, "bg sleep 30" non funzionerebbe perché sleep è un commandlet di Powershell. Start-Process funziona solo quando si effettua il fork di un processo.


7
Sono contento di aver trovato questa risposta. Stavo cercando l'equivalente di un meccanismo Unix a forcella due volte. A me sembra che qualcosa con cui è iniziato Start-Jobverrà ucciso quando uscirà la shell PS. Al contrario, sembra che qualcosa con cui è iniziato Start-Processcontinuerà a funzionare anche dopo l'uscita della shell PS. Questa è una grande differenza.
Pietro,

Sì: se si avvia uno script utilizzando Start-Process, sopravviverà alla chiusura della shell, ma se lo si è avviato da una finestra della console, rimarrà associato a quella finestra e la chiusura della finestra interromperà il processo.
Guss,

1
Nota, tuttavia, che non si può fare il reindirizzamento di uscita con Start-Processe quindi questo non funziona: Start-Process {ping -n 1000 example.com > ping__example.com.txt }. La stessa cosa Start-Jobfunziona bene (anche se è necessario utilizzare il percorso completo del file di output).
Nux

1
Tentativo di eseguire questa operazione per eseguire un server Web nodo e il processo termina quando esco da PowerShell. Qualcuno sa perché?
Jel,

@Jel No, ma il commento di Guss ne parla.
jpaugh

26

Sembra che il blocco di script passato Start-Jobnon sia eseguito con la stessa directory corrente del Start-Jobcomando, quindi assicurati di specificare il percorso completo se necessario.

Per esempio:

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

3
Ad esempio, se devo eseguire Git Pull nella riga di comando, devo specificare il percorso completo di tutto ...? È davvero fastidioso.
CMCDragonkai,

1
grazie, ottimo consiglio, sono andato in giro con un lavoro che non avrebbe funzionato, questo era il motivo.
Omni,

@CMCDragonkai oppure puoi fare solo Start-Job {cd C: \ Path \ To \ Repo; git pull}
Mahomedalid,

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

non ho ancora capito come ottenere stdout in tempo reale, start-job richiede di eseguire il polling di stdout con get-job

aggiornamento: non sono riuscito a iniziare il lavoro per fare facilmente quello che voglio, che è fondamentalmente bash e operatore. ecco il mio miglior hack finora

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
A partire da PowerShell v3.0 è possibile ottenere stdout in tempo reale in questo modo:Start-Job { Write-Output 'Hello world' } | Receive-Job -Wait
JamesQMurphy

19

Da PowerShell Core 6.0 sei in grado di scrivere &alla fine del comando e sarà equivalente a far girare la pipeline in background nella directory di lavoro corrente .

Non è equivalente a &in bash, è solo una sintassi migliore per le attuali funzioni dei lavori di PowerShell . Restituisce un oggetto lavoro in modo da poter usare tutti gli altri comandi da utilizzare per i lavori. Per esempio 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>

Se vuoi eseguire un paio di istruzioni in background puoi combinare l' &operatore di chiamata , il { }blocco di script e questo nuovo &operatore in background come qui:

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

Ecco alcune altre informazioni dalle pagine della documentazione:

da Novità di PowerShell Core 6.0 :

Supporta lo sfondo di condutture con e commerciale (&) (# 3360)

La messa &alla fine di una pipeline comporta l'esecuzione della pipeline come processo PowerShell. Quando una pipeline è in background, viene restituito un oggetto lavoro. Una volta che la pipeline è in esecuzione come lavoro, tutti i *-Jobcmdlet standard possono essere utilizzati per gestire il lavoro. Le variabili (ignorando le variabili specifiche del processo) utilizzate nella pipeline vengono automaticamente copiate nel lavoro, quindi Copy-Item $foo $bar &funziona. Il lavoro viene anche eseguito nella directory corrente anziché nella home directory dell'utente. Per ulteriori informazioni sui lavori PowerShell, vedere about_Jobs .

da about_operators / Ampersand background operator & :

Operatore di sfondo e commerciale &

Esegue la pipeline prima di essa in un processo PowerShell. L'operatore di e commerciale in background agisce in modo simile all'operatore di e commerciale di UNIX che esegue notoriamente il comando prima di esso come processo in background. L'operatore in background e commerciale è basato sui lavori di PowerShell, quindi condivide molte funzionalità Start-Job. Il seguente comando contiene l'utilizzo di base dell'operatore e commerciale in background.

Get-Process -Name pwsh &

Questo è funzionalmente equivalente al seguente utilizzo di Start-Job.

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

Poiché è funzionalmente equivalente all'uso Start-Job, l'operatore di sfondo e commerciale restituisce un Joboggetto proprio come Start-Job does. Ciò significa che sei in grado di utilizzare Receive-Jobe Remove-Jobproprio come faresti se avessi usato Start-Jobper iniziare il lavoro.

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

Produzione

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

Per ulteriori informazioni sui lavori PowerShell, vedere about_Jobs .


1
Grazie per questo fantastico riassunto che centinaia di pagine di MS non sono riuscite a realizzare.
not2qubit

Qualche idea su come gestire i lavori della console ? Ho provato con quanto sopra Receive-Job 3, ma non succede nulla.
not2qubit

@ not2qubit Non sono sicuro di cosa intendi per " lavori da console ". Quale comando esegui che vuoi eseguire in background?
Mariusz Pawelski,

Stavo usando un'app che avvia una console di Windows, ma non riesco a ottenere alcun output e spero di ottenerlo in modo simile al mondo nix fgper portare il lavoro in primo piano .
not2qubit,

@ not2qubit Sfortunatamente sembra che non ci sia nulla di simile a unix fgin PowerShell :( Ricordo di averlo cercato, ma non sono riuscito a trovare nulla
Mariusz Pawelski,

17

È possibile utilizzare i cmdlet del lavoro PowerShell per raggiungere i propri obiettivi.

In PowerShell sono disponibili 6 cmdlet relativi al lavoro.

  • Get-Job
    • Ottiene i processi in background di Windows PowerShell in esecuzione nella sessione corrente
  • Receive-Job
    • Ottiene i risultati dei processi in background di Windows PowerShell nella sessione corrente
  • Remove-Job
    • Elimina un processo in background di Windows PowerShell
  • Start-Job
    • Avvia un processo in background di Windows PowerShell
  • Stop-Job
    • Interrompe un processo in background di Windows PowerShell
  • Wait-Job
    • Elimina il prompt dei comandi fino al completamento di uno o tutti i processi in background di Windows PowerShell in esecuzione nella sessione

Se interessante, è possibile scaricare l'esempio Come creare un processo in background in PowerShell


1
Buona risposta per quanto riguarda Powershell 3+. Qual è la differenza tra i cmdlet del lavoro e le risposte precedenti?
Jeremy Hajek,

3

Puoi fare qualcosa del genere.

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

E se vuoi aspettarlo:

$a | wait-process

Bonus osx o versione linux:

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

Ho un esempio di script pinger. Gli arg sono passati come un array:

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

start interromperà il processo e restituirà il controllo al chiamante. Maggiori informazioni qui
Aethalides,

@Aethalides start è in realtà un alias per il processo di avvio in PowerShell.
js2010,


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.