Powershell tương đương với bash ampersand (&) để forking / chạy các tiến trình nền


157

Trong bash, ampersand (&) có thể được sử dụng để chạy lệnh trong nền và trả lại điều khiển tương tác cho người dùng trước khi lệnh chạy xong. Có một phương pháp tương đương để làm điều này trong Powershell?

Ví dụ về cách sử dụng trong bash:

 sleep 30 &

Câu trả lời:


123

Miễn là lệnh là tệp thực thi hoặc tệp có tệp thực thi được liên kết, hãy sử dụng Start-Process (có sẵn từ v2):

Start-Process -NoNewWindow ping google.com

Bạn cũng có thể thêm điều này như một chức năng trong hồ sơ của bạn:

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

và sau đó lời cầu khẩn trở thành:

bg ping google.com

Theo tôi, Start-Job là một sự quá mức cần thiết cho trường hợp sử dụng đơn giản để chạy một tiến trình trong nền:

  1. Start-Job không có quyền truy cập vào phạm vi hiện tại của bạn (vì nó chạy trong một phiên riêng). Bạn không thể thực hiện "Bắt đầu công việc {notepad $ myfile}"
  2. Start-Job không bảo vệ thư mục hiện tại (vì nó chạy trong một phiên riêng). Bạn không thể thực hiện "Bắt đầu công việc {notepad myfile.txt}" trong đó myfile.txt nằm trong thư mục hiện tại.
  3. Đầu ra không được hiển thị tự động. Bạn cần chạy Nhận công việc với ID của công việc làm tham số.

LƯU Ý: Về ví dụ ban đầu của bạn, "bg ngủ 30" sẽ không hoạt động vì giấc ngủ là một lệnh của Powershell. Start-Process chỉ hoạt động khi bạn thực sự rẽ nhánh một tiến trình.


7
Vui mừng tôi tìm thấy câu trả lời này. Tôi đang tìm kiếm tương đương với một cơ chế hai lần Unix. Đối với tôi, dường như thứ gì đó bắt đầu Start-Jobsẽ bị giết khi vỏ PS thoát ra. Ngược lại, có vẻ như một cái gì đó bắt đầu với Start-Processsẽ tiếp tục chạy sau khi vỏ PS thoát ra. Đây là một sự khác biệt lớn .
peterh

Có - nếu bạn bắt đầu sử dụng tập lệnh Start-Process, nó sẽ tồn tại khi kết thúc shell, nhưng nếu bạn khởi động nó từ cửa sổ giao diện điều khiển thì nó vẫn bị ràng buộc với cửa sổ đó và việc đóng cửa sổ sẽ chấm dứt quá trình.
Guss

1
Tuy nhiên, lưu ý rằng bạn không thể thực hiện chuyển hướng đầu ra Start-Processvà vì vậy điều này sẽ KHÔNG hoạt động : Start-Process {ping -n 1000 example.com > ping__example.com.txt }. Điều tương tự với Start-Jobhoạt động tốt (mặc dù bạn phải sử dụng đường dẫn đầy đủ đến tệp đầu ra).
Nux

1
Đã cố gắng làm điều này để chạy một máy chủ web nút và quá trình kết thúc khi tôi thoát khỏi powershell. Có ai biết tại sao không?
Jel

@Jel Không, nhưng bình luận của Guss nói về điều đó.
jpaugh

26

Có vẻ như khối tập lệnh được truyền đến Start-Jobkhông được thực thi với cùng thư mục hiện tại với Start-Joblệnh, vì vậy hãy đảm bảo chỉ định đường dẫn đủ điều kiện nếu cần.

Ví dụ:

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

3
Vì vậy, ví dụ nếu tôi cần chạy Git Pull trong dòng lệnh, tôi cần chỉ định đường dẫn đầy đủ đến mọi thứ ...? Điều đó thực sự gây phiền nhiễu.
CMCDragonkai

1
cảm ơn, mẹo tuyệt vời, đã đi xung quanh với một công việc sẽ không chạy, đây là lý do tại sao.
Omni

@CMCDragonkai hoặc bạn chỉ có thể thực hiện Start-Job {cd C: \ Path \ To \ Repo; git pull}
Mahomedalid

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

Tôi vẫn chưa tìm ra làm thế nào để có được stdout trong thời gian thực, công việc bắt đầu đòi hỏi bạn phải thăm dò ý kiến ​​với công việc

cập nhật: tôi không thể bắt đầu công việc để dễ dàng làm những gì tôi muốn mà về cơ bản là bash & toán tử. Đây là bản hack tốt nhất của tôi cho đến nay

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
Kể từ PowerShell v3.0, bạn có thể nhận được thiết bị xuất chuẩn trong thời gian thực như thế này:Start-Job { Write-Output 'Hello world' } | Receive-Job -Wait
JamesQMurphy

19

Từ PowerShell Core 6.0, bạn có thể viết &ở cuối lệnh và nó sẽ tương đương với việc chạy đường ống dẫn của bạn trong nền trong thư mục làm việc hiện tại .

Nó không tương đương với &bash, nó chỉ là một cú pháp đẹp hơn cho tính năng công việc PowerShell hiện tại . Nó trả về một đối tượng công việc để bạn có thể sử dụng tất cả các lệnh khác mà bạn sẽ sử dụng cho các công việc. Ví dụ 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>

Nếu bạn muốn thực thi một vài câu lệnh trong nền, bạn có thể kết hợp &toán tử cuộc gọi , { }khối tập lệnh&toán tử nền mới này như ở đây:

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

Dưới đây là một số thông tin từ các trang tài liệu:

từ những gì mới trong PowerShell Core 6.0 :

Hỗ trợ tạo nền cho các đường ống bằng ký hiệu (&) (# 3360)

Đặt &ở cuối đường ống làm cho đường ống được chạy như một công việc PowerShell. Khi một đường ống được làm nền, một đối tượng công việc được trả về. Khi đường ống đang hoạt động như một công việc, tất cả các *-Joblệnh ghép ngắn tiêu chuẩn có thể được sử dụng để quản lý công việc. Các biến (bỏ qua các biến cụ thể của quá trình) được sử dụng trong đường ống được tự động sao chép vào công việc để Copy-Item $foo $bar &chỉ hoạt động. Công việc cũng được chạy trong thư mục hiện tại thay vì thư mục chính của người dùng. Để biết thêm thông tin về các công việc PowerShell, hãy xem about_Jobs .

từ about_operators / toán tử nền Ampersand & :

Toán tử Ampersand &

Chạy đường ống trước khi nó hoạt động trong PowerShell. Toán tử ampersand hoạt động tương tự như "toán tử ampersand" UNIX, vốn nổi tiếng chạy lệnh trước khi nó là một quá trình nền. Toán tử ampersand nền được xây dựng dựa trên các công việc PowerShell để nó chia sẻ rất nhiều chức năng Start-Job. Lệnh sau chứa cách sử dụng cơ bản của toán tử nền và dấu.

Get-Process -Name pwsh &

Đây là chức năng tương đương với việc sử dụng sau đây Start-Job.

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

Vì nó có chức năng tương đương với việc sử dụng Start-Job, toán tử nền và trả về một Jobđối tượng giống như Start-Job does. Điều này có nghĩa là bạn có thể sử dụng Receive-JobRemove-Jobgiống như bạn đã từng sử dụng Start-Jobđể bắt đầu công việc.

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

Đầu ra

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

Để biết thêm thông tin về các công việc PowerShell, hãy xem about_Jobs .


1
Cảm ơn vì bản tóm tắt tuyệt vời này mà 100 trang MS không thể thực hiện được.
not2qubit

Bất kỳ ý tưởng làm thế nào để xử lý công việc giao diện điều khiển ? Tôi đã thử ở trên với Receive-Job 3, nhưng không có gì xảy ra.
not2qubit

@ not2qubit Tôi không chắc ý của bạn là " công việc bàn điều khiển ". Lệnh nào bạn chạy mà bạn muốn chạy trong nền?
Mariusz Pawelski

Tôi đang sử dụng một ứng dụng khởi chạy bảng điều khiển windows, nhưng tôi không thể nhận được bất kỳ đầu ra nào và hy vọng sẽ có được nó tương tự như thế giới nix fgđể đưa công việc lên * tiền cảnh .
not2qubit

@ not2qubit Thật không may là dường như không có thứ gì tương tự như unix fgtrong powershell :( Tôi nhớ là đã tìm nó, nhưng không thể tìm thấy bất cứ thứ gì
Mariusz Pawelski

17

Bạn có thể sử dụng các lệnh ghép ngắn PowerShell để đạt được mục tiêu của mình.

Có 6 lệnh ghép ngắn liên quan đến công việc có sẵn trong PowerShell.

  • Nhận việc
    • Nhận các công việc nền Windows PowerShell đang chạy trong phiên hiện tại
  • Nhận công việc
    • Nhận kết quả của các công việc nền Windows PowerShell trong phiên hiện tại
  • Loại bỏ công việc
    • Xóa một công việc nền Windows PowerShell
  • Bắt đầu công việc
    • Bắt đầu một công việc nền Windows PowerShell
  • Dừng công việc
    • Dừng công việc nền Windows PowerShell
  • Công việc chờ
    • Loại bỏ dấu nhắc lệnh cho đến khi một hoặc tất cả các công việc nền Windows PowerShell đang chạy trong phiên hoàn tất

Nếu thú vị về điều đó, bạn có thể tải xuống mẫu Cách tạo công việc nền trong PowerShell


1
Câu trả lời tốt vì nó liên quan đến Powershell 3+. Sự khác biệt giữa lệnh ghép ngắn công việc và câu trả lời trước là gì?
Jeremy Hajek

3

Bạn có thể làm một cái gì đó như thế này.

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

Và nếu bạn muốn chờ đợi nó:

$a | wait-process

Phần thưởng osx hoặc phiên bản linux:

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

Ví dụ kịch bản pinger tôi có. Các đối số được truyền dưới dạng một mảng:

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

start sẽ rẽ nhánh quá trình và trả lại quyền điều khiển cho người gọi. Thêm thông tin ở đây
Aethalides

@Aethalides start thực sự là một bí danh cho quá trình bắt đầu trong powershell.
js2010


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.