Вопрос или проблема
У меня есть скрипт PowerShell для установки программного обеспечения на удаленные компьютеры.
На сегодняшний день я успешно использую следующий код:
$prog = "ping"
$arg = "localhost"
$computername = "MACHINE01"
invoke-command -computername $computername {param($p,$a)& $p $a} -ArgumentList $prog,$arg
Теперь мне нужно установить MSI, например, ‘msiexec /i c:\file.msi /passive’.
Я не могу заставить MSIEXEC воспринимать все после ‘MSIEXEC’ как параметры. Вместо этого PowerShell пытается выполнить это как одну большую команду. Я пробовал множество вещей, в основном связанных с размещением литералов в кавычках, но не смог заставить это работать.
Я сейчас отказался от оператора вызова (&) в пользу ‘Start-Process’, который имеет параметр ‘-ArgumentList’. MSI теперь выполняется корректно. Отлично!
invoke-command -computername $computername {param($p,$a) start-process $p -argumentlist $a -nonewwindow -wait -redirectstandardoutput c:\output.txt; get-content c:\output.txt} -ArgumentList $prog,$arg
Проблема с ‘Start-Process’ в том, что он не выводит никакого консольного вывода, когда запускается удаленно с использованием ‘Invoke-Command’. Мне пришлось прибегнуть к перенаправлению вывода в файл, а затем чтению файла. Есть ли лучший способ?
Я бы попробовал передать это в командлет tee-object, а затем сохранить ваш файл там, если это необходимо (не знаю, сработает ли отправка вывода файла в $null, жаль, что это не linux, и мы не можем отправить это в /dev/null, но я отвлекся)
Это командлет tee-object http://technet.microsoft.com/en-us/library/ee177014.aspx
invoke-command -computername $computername {param($p,$a) start-process $p -argumentlist $a -nonewwindow -wait | tee-object -file c:\output.txt} -ArgumentList $prog,$arg
это непроверенный код, но в общем-то это именно то, что вам нужно.
invoke-command -computername $computername {param($p,$a) start-process $p -argumentlist $a -nonewwindow -wait | tee-object -file $null} -ArgumentList $prog,$arg
тоже может сработать.
Ответ или решение
Для выполнения команды Start-Process
удалённо и получения стандартного вывода при использовании PowerShell, необходимо учитывать несколько важных аспектов. Когда вы запускаете процессы удалённо с помощью Invoke-Command
, стандартный вывод и стандартные ошибки не отображаются в консоли вызова. Вместо этого рекомендуется использовать перенаправление вывода в файл или использовать команды, которые позволяют отправлять вывод обратно в консоль.
Решение проблемы с выводом при использовании Start-Process
Ваш текущий подход с Start-Process
является корректным, однако, как вы уже заметили, он не возвращает вывод непосредственно в консоль. Чтобы решить эту проблему, вы можете воспользоваться несколькими альтернативными методами. Я предложу несколько решений:
1. Использование Pipe
и Tee-Object
Вы можете использовать Tee-Object
, который позволяет захватывать вывод и одновременно отправлять его в файл. Пример кода может выглядеть следующим образом:
$prog = "msiexec"
$arg = "/i C:\file.msi /passive"
$computername = "MACHINE01"
Invoke-Command -ComputerName $computername {
param($p, $a)
Start-Process $p -ArgumentList $a -NoNewWindow -Wait | Tee-Object -FilePath C:\output.txt
} -ArgumentList $prog, $arg
Этот код устанавливает MSI-приложение и записывает весь вывод в файл C:\output.txt
. Кроме того, если вы хотите видеть вывод в консоли, вы можете просто пропустить создание файла или сохранить его для последующего анализа.
2. Использование -RedirectStandardOutput
Если вы хотите сохранить вывод в файл и одновременно выводить его в консоль, используйте опцию -RedirectStandardOutput
:
Invoke-Command -ComputerName $computername {
param($p, $a)
Start-Process $p -ArgumentList $a -NoNewWindow -Wait -RedirectStandardOutput C:\output.txt
Get-Content C:\output.txt
} -ArgumentList $prog, $arg
Этот метод сохраняет вывод в файл и затем выводит его с помощью Get-Content
, что позволяет вам просматривать результат выполнения сразу после завершения процесса.
3. Использование Invoke-Expression
Если вы хотите избежать проблем с передачей аргументов и стандартного вывода, можно использовать Invoke-Expression
. Однако, это может быть менее безопасно, так как оно выполняет строку как команду. Пример:
$command = 'msiexec /i C:\file.msi /passive'
Invoke-Command -ComputerName $computername {
param($cmd)
Invoke-Expression $cmd
} -ArgumentList $command
Заключение
Хотя Start-Process
не выводит штатный вывод и ошибки в консоль при удалённом запуске, существуют эффективные методы для обработки этого ограничения. Использование Tee-Object
, перенаправление вывода и другие техники позволяют вам продолжать работать независимо от сложности задачи. Правильный подход обеспечит как сохранение логов, так и возможность видеть вывод в реальном времени, что упрощает администрирование и диагностику в вашей среде.