Еквівалент Powershell bash ampersand (&) для розгортання / запуску фонових процесів


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 не зберігає поточний каталог (оскільки він працює в окремому сеансі). Ви не можете виконати "Start-Job {notepad myfile.txt}", де myfile.txt знаходиться у поточному каталозі.
  3. Вихід не відображається автоматично. Вам потрібно запустити Receive-Job з ідентифікатором завдання як параметром.

ПРИМІТКА. Що стосується вашого початкового прикладу, "bg sleep 30" не буде працювати, оскільки сон - це команда Powershell. Start-Process працює лише тоді, коли ви фактично розщедрили процес.


7
Радий, що знайшов цю відповідь. Я шукав еквівалент механізму вилки Unix двічі. Мені здається, що щось, що почалося з Start-Jobцього, буде вбито, коли оболонка PS вийде. На противагу цьому, здається, що щось, розпочате з Start-Process, продовжить працювати після закінчення роботи оболонки PS. Це головна різниця.
peterh

Так - якщо ви запускаєте сценарій з використанням Start-Process, він переживе завершення оболонки, але якщо ви запустили його з вікна консолі, він залишається прив’язаним до цього вікна, а закриття вікна завершить процес.
Гасс

1
Однак зверніть увагу , що ви не можете зробити перенаправлення виведення з Start-Processі так цього не буде працювати: Start-Process {ping -n 1000 example.com > ping__example.com.txt }. Те ж саме і з Start-Jobвідмінно працює (хоча вам доведеться використовувати повний шлях до вихідного файлу).
Nux

1
Спроба зробити це запустити веб-сервер вузла, і процес припиняється, коли я виходжу з shellhell. Хтось знає, чому?
1616

@Jel Ні, але коментар Гасса говорить про це.
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

1
дякую, чудова порада, займаючись роботою, яка не бігла б, це було причиною того.
Омні

@CMCDragonkai або ви можете зробити просто Start-Job {cd C: \ Path \ To \ Repo; git pull}
Махомедалід

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

я ще не зрозумів, як отримати stdout в режимі реального часу, старт-робота вимагає від вас опитувати stdout за допомогою get-job

оновлення: я не міг розпочати роботу, щоб легко робити те, що я хочу, а це в основному bash & operator. ось мій найкращий хак до цих пір

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 ви можете отримати stdout в реальному часі так:Start-Job { Write-Output 'Hello world' } | Receive-Job -Wait
JamesQMurphy

19

З PowerShell Core 6.0 ви можете писати &в кінці команди, і це буде еквівалентно запуску конвеєра у фоновому режимі в поточному робочому каталозі .

Це не еквівалентно &в БАШЕЄВ, це просто краще синтаксис для поточного 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>

Якщо ви хочете виконати пару операторів у фоновому режимі, ви можете комбінувати &оператор виклику , { }блок скриптів і цей новий &фоновий оператор, як тут:

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

Ось додаткова інформація на сторінках документації:

з Що нового в PowerShell 6.0 Ядра :

Підтримка фонового покриття трубопроводів амперсандом (&) (# 3360)

Поміщення &в кінці трубопроводу призводить до того, що конвеєр буде працювати як PowerShell. Коли трубопровід є фоновим, об'єкт завдання повертається. Після того як конвеєр працює як робота, всі стандартні *-Jobкомандлети можуть бути використані для управління роботою. Змінні (ігнорування змінних, що стосуються певного процесу), що використовуються в конвеєрі, автоматично копіюються в завдання, так що це Copy-Item $foo $bar &просто працює. Завдання також виконується в поточному каталозі замість домашнього каталогу користувача. Щоб отримати докладнішу інформацію про завдання PowerShell, перегляньте сторінку about_Jobs .

від about_operators / фон оператора Ampersand & :

Оператор фону Ampersand &

Запускає трубопровід перед ним у роботі PowerShell. Оператор фону ampersand діє подібно до "оператора ampersand" UNIX, який чудово виконує команду перед ним як фоновий процес. Фоновий оператор ampersand побудований на основі завдань PowerShell, тому він має багато функціональних можливостей Start-Job. Наступна команда містить основне використання оператора фону ampersand.

Get-Process -Name pwsh &

Це функціонально еквівалентно наступному використанню Start-Job.

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

Оскільки він функціонально еквівалентний використанню Start-Job, оператор фону ampersand повертає Jobоб'єкт так само, як Start-Job does. Це означає, що ви вмієте користуватися Receive-Jobі так Remove-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, але я не можу отримати жодного результату, і сподівався отримати його аналогічно світу нікс fgдля виведення роботи на передній план * .
not2qubit

@ not2qubit На жаль, здається, що у Unix fgу powershell немає подібного: схоже, я шукав його, але нічого не міг знайти
Mariusz Pawelski

17

Ви можете використовувати командлети для роботи PowerShell для досягнення своїх цілей.

У PowerShell доступно 6 командлетів, пов'язаних з роботою.

  • Get-Job
    • Отримує фонові завдання Windows PowerShell, які виконуються в поточному сеансі
  • Прийом-робота
    • Отримує результати робочих завдань Windows PowerShell в поточному сеансі
  • Видалити-Робота
    • Видаляє фонове завдання Windows PowerShell
  • Початок роботи
    • Починає фонове завдання Windows PowerShell
  • Зупинка-робота
    • Зупиняє фонове завдання Windows PowerShell
  • Зачекайте-робота
    • Пригнічує командний рядок, поки не завершиться одне або всі фонові завдання Windows PowerShell, що виконуються в сеансі

Якщо цікаво про це, ви можете завантажити зразок Як створити фонове завдання в PowerShell


1
Хороша відповідь, оскільки це стосується Powershell 3+. Яка різниця між командлетами завдання та попередніми відповідями?
Джеремі Гаек

3

Можна зробити щось подібне.

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

А якщо ви хочете дочекатися цього:

$a | wait-process

Версія Bonus osx або linux:

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

Приклад сценарію pinger у мене є. Аргументи передаються як масив:

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

start буде розправляти процес і повертати контроль абоненту. Більше інформації тут
Еталіди

@Aethalides start - це фактично псевдонім для запуску-процесу в powershell.
js2010


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.