Эквивалент Powershell bash амперсанд (&) для фоновых процессов с использованием forking/running

В bash амперсанд (&) можно использовать для запуска команды в фоновом режиме и возврата интерактивного элемента управления пользователю до окончания выполнения команды. Есть ли эквивалентный метод для этого в Powershell?

Пример использования в bash:

 sleep 30 &

Ответ 1

Есть несколько ответов на этот вопрос.

  1. Вы не можете легко сделать это в версии 1
  2. Версия 2 (теперь в Community Tech Preview 2) имеет эту функцию, она называется Job (ранее PSJob). Узнайте больше об этом здесь или здесь.
  3. На самом деле вы можете сделать это трудным путем в v1, не стесняйтесь, но я никогда не беспокоился.

Ответ 2

Пока команда является исполняемым файлом или файлом, который имеет связанный с ним исполняемый файл, используйте Start-Process (доступный из v2):

Start-Process -NoNewWindow ping google.com

Вы также можете добавить это как функцию в свой профиль:

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

а затем вызов будет:

bg ping google.com

На мой взгляд, Start-Job является излишним для простого использования процесса в фоновом режиме:

  • Start-Job не имеет доступа к вашей существующей области (поскольку она выполняется в отдельном сеансе). Вы не можете выполнить "Start-Job {notepad $myfile}"
  • Start-Job не сохраняет текущий каталог (поскольку он запускается в отдельном сеансе). Вы не можете выполнить "Start-Job {notepad myfile.txt}", где myfile.txt находится в текущем каталоге.
  • Выход не отображается автоматически. Вам необходимо запустить Receive-Job с идентификатором задания в качестве параметра.

ПРИМЕЧАНИЕ. Что касается вашего первоначального примера, "bg sleep 30" не будет работать, потому что sleep - это командный файл Powershell. Start-Process работает только тогда, когда вы фактически запускаете процесс.

Ответ 3

Кажется, что блок script, переданный в Start-Job, не выполняется с тем же текущим каталогом, что и команда Start-Job, поэтому обязательно укажите полный путь, если необходимо.

Например:

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

Ответ 4

ps2> start-job {start-sleep 20}

Я еще не понял, как получить stdout в реальном времени, start-job требует, чтобы вы опросили stdout с get-job

update: я не мог начать работу, чтобы легко делать то, что хочу, в основном это bash и оператор. вот мой лучший хак до сих пор

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

Ответ 5

Командлеты PowerShell можно использовать для достижения ваших целей.

В PowerShell доступно 6 командлетов, связанных с работой.

  • Get-Job
    • Получает фоновые задания Windows PowerShell, запущенные в текущем сеансе
  • Receive-Job
    • Получает результаты фоновых заданий Windows PowerShell в текущем сеансе
  • Remove-Job
    • Удаляет фоновое задание Windows PowerShell.
  • Start-Job
    • Запускает фоновое задание Windows PowerShell.
  • Stop-Job
    • Останавливает фоновое задание Windows PowerShell.
  • Wait-Job
    • Подавляет командную строку до тех пор, пока не будет завершено выполнение одного или всех фоновых заданий Windows PowerShell в сеансе

Если интересно, вы можете загрузить образец Как создать фоновое задание в PowerShell

Ответ 6

Из 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>

Если вы хотите выполнить пару операторов в фоновом режиме, вы можете объединить оператор & call, блок сценария { } и этот новый оператор & background, как здесь:

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

Вот еще немного информации со страниц документации:

Что нового в PowerShell Core 6.0:

Поддержка фоновой обработки трубопроводов с помощью амперсанда (&) (# 3360)

Если поставить & в конце конвейера, конвейер будет запущен как задание PowerShell. Когда конвейер находится на заднем плане, возвращается объект задания. Когда конвейер запускается как задание, все стандартные командлеты *-Job можно использовать для управления заданием. Переменные (игнорирующие переменные, специфичные для процесса), используемые в конвейере, автоматически копируются в задание, поэтому Copy-Item $foo $bar & просто работает. Задание также выполняется в текущем каталоге вместо домашнего каталога пользователя. Для получения дополнительной информации о заданиях PowerShell см. About_Jobs.

из about_operators/Ampersand background operator &:

Амперсанд фоновый оператор &

Запускает конвейер перед ним в задании PowerShell. Фоновый оператор амперсанда действует аналогично "оператору амперсанда" в UNIX, который классно запускает команду перед ним как фоновый процесс. Фоновый оператор амперсанда построен поверх заданий PowerShell, поэтому он имеет много Start-Job с Start-Job. Следующая команда содержит базовое использование оператора амперсанда в качестве фона.

Get-Process -Name pwsh &

Это функционально эквивалентно следующему использованию Start-Job.

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

Поскольку это функционально эквивалентно использованию Start-Job, фоновый оператор амперсанда возвращает объект 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.

Ответ 7

Вы можете сделать что-то вроде этого.

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

done

И если вы хотите подождать этого:

$a | wait-process

Бонусная версия для OSX или Linux:

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

Пример сценария Pinger у меня есть. Аргументы передаются в виде массива:

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

Ответ 9

ТЛ; др

Start-Process powershell { sleep 30 }