Powershell setara dengan bash ampersand (&) untuk forking / menjalankan proses latar belakang

158

Dalam bash, ampersand (&) dapat digunakan untuk menjalankan perintah di latar belakang dan mengembalikan kontrol interaktif kepada pengguna sebelum perintah selesai dijalankan. Apakah ada metode yang setara untuk melakukan ini di Powershell?

Contoh penggunaan dalam bash:

 sleep 30 &
eddiegroves
sumber

Jawaban:

124

Selama perintahnya adalah file yang dapat dieksekusi atau file yang memiliki file yang dapat dieksekusi terkait, gunakan Mulai-Proses (tersedia dari v2):

Start-Process -NoNewWindow ping google.com

Anda juga dapat menambahkan ini sebagai fungsi di profil Anda:

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

dan kemudian doa menjadi:

bg ping google.com

Menurut pendapat saya, Start-Job adalah kerja keras untuk kasus penggunaan sederhana menjalankan proses di latar belakang:

  1. Start-Job tidak memiliki akses ke ruang lingkup Anda yang ada (karena berjalan dalam sesi terpisah). Anda tidak dapat melakukan "Start-Job {notepad $ myfile}"
  2. Start-Job tidak mempertahankan direktori saat ini (karena berjalan dalam sesi terpisah). Anda tidak dapat melakukan "Start-Job {notepad myfile.txt}" di mana myfile.txt berada di direktori saat ini.
  3. Output tidak ditampilkan secara otomatis. Anda perlu menjalankan Receive-Job dengan ID pekerjaan sebagai parameter.

CATATAN: Mengenai contoh awal Anda, "bg sleep 30" tidak akan berfungsi karena sleep adalah commandlet Powershell. Mulai-Proses hanya berfungsi ketika Anda benar-benar melakukan suatu proses.

Bogdan Calmac
sumber
7
Senang saya menemukan jawaban ini. Saya mencari mekanisme yang setara dengan Unix fork-2x. Bagi saya tampaknya sesuatu yang dimulai Start-Jobakan terbunuh ketika shell PS keluar. Sebaliknya, sesuatu yang dimulai dengan Start-Processakan terus berjalan setelah PS shell keluar. Ini perbedaan utama .
peterh
Ya - jika Anda mulai menggunakan skrip Start-Process, skrip ini akan bertahan, tetapi jika Anda memulainya dari jendela konsol maka ia tetap terikat ke jendela itu dan menutup jendela itu akan menghentikan prosesnya.
Guss
1
Catatan namun yang tidak dapat Anda lakukan output redirection dengan Start-Processdan jadi ini akan tidak bekerja: Start-Process {ping -n 1000 example.com > ping__example.com.txt }. Hal yang sama dengan Start-Jobberfungsi dengan baik (meskipun Anda harus menggunakan path lengkap ke file output).
Nux
1
Mencoba melakukan ini untuk menjalankan server web node, dan proses berakhir ketika saya keluar dari PowerShell. Adakah yang tahu kenapa?
Jel
@Jel Tidak, tapi komentar Guss berbicara tentang itu.
jpaugh
26

Tampaknya blok skrip yang diteruskan ke Start-Jobtidak dieksekusi dengan direktori saat ini sama dengan Start-Jobperintah, jadi pastikan untuk menentukan jalur yang memenuhi syarat jika diperlukan.

Sebagai contoh:

Start-Job { C:\absolute\path\to\command.exe --afileparameter C:\absolute\path\to\file.txt }
Gian Marco
sumber
3
Jadi misalnya jika saya perlu menjalankan Git Pull di commandline, saya perlu menentukan path lengkap untuk semuanya ...? Itu sangat menjengkelkan.
CMCDragonkai
1
terima kasih, tip yang bagus, sudah berkeliling dengan pekerjaan yang tidak akan berjalan, ini adalah alasan mengapa.
Omni
@CMCDragonkai atau Anda bisa melakukan Start-Job {cd C: \ Path \ To \ Repo; git pull}
Mahomedalid
21
ps2> start-job {start-sleep 20}

saya belum menemukan cara untuk mendapatkan stdout secara langsung, pekerjaan awal mengharuskan Anda untuk memilih stdout dengan mendapatkan pekerjaan

pembaruan: saya tidak dapat memulai pekerjaan dengan mudah melakukan apa yang saya inginkan yang pada dasarnya adalah bash & operator. inilah hack terbaik saya sejauh ini

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
sumber
1
Pada PowerShell v3.0 Anda bisa mendapatkan stdout secara realtime seperti ini:Start-Job { Write-Output 'Hello world' } | Receive-Job -Wait
JamesQMurphy
19

Dari PowerShell Core 6.0 Anda dapat menulis &di akhir perintah dan itu akan setara dengan menjalankan pipeline di latar belakang di direktori kerja saat ini .

Ini tidak sama dengan &di bash, itu hanya sintaks yang lebih bagus untuk fitur pekerjaan PowerShell saat ini. Ini mengembalikan objek pekerjaan sehingga Anda dapat menggunakan semua perintah lain yang akan Anda gunakan untuk pekerjaan. Sebagai contoh 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>

Jika Anda ingin menjalankan beberapa pernyataan di latar belakang, Anda dapat menggabungkan &operator panggilan , { }blok skrip dan &operator latar belakang baru ini seperti di sini:

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

Berikut ini beberapa info dari halaman dokumentasi:

dari Apa yang Baru di PowerShell Core 6.0 :

Mendukung latar belakang pipa dengan ampersand (&) (# 3360)

Menempatkan &di ujung pipa menyebabkan pipa dijalankan sebagai pekerjaan PowerShell. Ketika pipa dilatar belakangi, objek pekerjaan dikembalikan. Setelah pipa berjalan sebagai pekerjaan, semua *-Jobcmdlet standar dapat digunakan untuk mengelola pekerjaan. Variabel (mengabaikan variabel proses-spesifik) yang digunakan dalam pipa secara otomatis disalin ke pekerjaan sehingga Copy-Item $foo $bar &berfungsi. Pekerjaan juga dijalankan di direktori saat ini, bukan direktori home pengguna. Untuk informasi lebih lanjut tentang pekerjaan PowerShell, lihat about_Jobs .

dari about_operators / Ampersand operator latar belakang & :

Ampersand operator latar belakang &

Jalankan pipa sebelum itu dalam pekerjaan PowerShell. Operator latar belakang ampersand bertindak serupa dengan "operator ampersand" UNIX yang terkenal menjalankan perintah sebelumnya sebagai proses latar belakang. Operator latar belakang ampersand dibuat di atas pekerjaan PowerShell sehingga berbagi banyak fungsi dengan Start-Job. Perintah berikut berisi penggunaan dasar dari operator ampersand background.

Get-Process -Name pwsh &

Ini secara fungsional setara dengan penggunaan berikut dari Start-Job.

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

Karena secara fungsional setara dengan menggunakan Start-Job, operator latar belakang dan ampers mengembalikan Jobobjek seperti Start-Job does. Ini berarti bahwa Anda dapat menggunakan Receive-Jobdan Remove-Jobseperti yang Anda lakukan jika Anda sudah Start-Jobmemulai pekerjaan.

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

Keluaran

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

Untuk informasi lebih lanjut tentang pekerjaan PowerShell, lihat about_Jobs .

Mariusz Pawelski
sumber
1
Terima kasih untuk ringkasan yang luar biasa ini yang tidak dapat dicapai oleh 100 halaman MS.
not2qubit
Adakah yang tahu bagaimana menangani pekerjaan konsol ? Saya mencoba di atas dengan Receive-Job 3, tetapi tidak ada yang terjadi.
not2qubit
@ not2qubit Saya tidak yakin apa yang Anda maksud dengan " pekerjaan konsol ". Perintah apa yang Anda jalankan yang ingin Anda jalankan di latar belakang?
Mariusz Pawelski
Saya menggunakan aplikasi yang meluncurkan konsol windows, tapi saya tidak bisa mendapatkan output apa pun dan berharap untuk mendapatkannya mirip dengan dunia nix fguntuk membawa pekerjaan ke * foreground .
not2qubit
@ not2qubit Sayangnya sepertinya tidak ada yang mirip dengan unix fgdi powershell :( Saya ingat mencarinya, tetapi tidak dapat menemukan apa pun
Mariusz Pawelski
17

Anda dapat menggunakan cmdlet pekerjaan PowerShell untuk mencapai tujuan Anda.

Ada 6 cmdlet terkait pekerjaan yang tersedia di PowerShell.

  • Mendapat pekerjaan
    • Mendapat pekerjaan latar belakang Windows PowerShell yang sedang berjalan di sesi saat ini
  • Terima-Pekerjaan
    • Mendapat hasil pekerjaan latar belakang Windows PowerShell di sesi saat ini
  • Hapus-Pekerjaan
    • Menghapus pekerjaan latar belakang Windows PowerShell
  • Mulai-Pekerjaan
    • Mulai pekerjaan latar belakang Windows PowerShell
  • Stop-Job
    • Menghentikan pekerjaan latar belakang Windows PowerShell
  • Tunggu-Kerja
    • Menekan prompt perintah hingga satu atau semua pekerjaan latar belakang Windows PowerShell yang berjalan di sesi selesai

Jika menarik tentang hal itu, Anda dapat mengunduh sampel Cara membuat pekerjaan latar belakang di PowerShell

Eric
sumber
1
Jawaban yang bagus karena berkaitan dengan Powershell 3+. Apa perbedaan antara cmdlet pekerjaan dan jawaban sebelumnya?
Jeremy Hajek
3

Anda dapat melakukan sesuatu seperti ini.

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

Dan jika Anda ingin menunggu untuk itu:

$a | wait-process

Bonus osx atau versi linux:

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

Contoh skrip pinger yang saya miliki. Args dilewatkan sebagai array:

$1 = start -n powershell pinger,comp001 -pa
js2010
sumber
start akan memotong proses dan mengembalikan kontrol ke pemanggil. Info lebih lanjut di sini
Aethalides
@Aethalides start sebenarnya adalah alias untuk memulai proses di PowerShell.
js2010
2

tl; dr

Start-Process powershell { sleep 30 }
ruang angkasa luar
sumber