Как вывести что-то в PowerShell
Я запускаю PowerShell script из пакетного файла. script извлекает веб-страницу и проверяет, является ли содержимое страницы строкой "ОК".
PowerShell script возвращает уровень ошибок пакету script.
Пакет script выполняется программой ScriptFTP, программой автоматизации FTP. Если возникает ошибка, я могу заставить ScriptFTP отправлять полный консольный вывод администратору через E-Mail.
В PowerShell script я хотел бы выводить возвращаемое значение с веб-сайта, если оно не является "ОК", поэтому сообщение об ошибке включается в вывод консоли и, таким образом, в почте статуса.
Я новичок в PowerShell и не знаю, какую функцию вывода использовать для этого. Я вижу три:
- Write-Host
- Write-Output
- Write-Error
Каким будет правильное использование для записи в эквивалент Windows stdout
?
Ответы
Ответ 1
Простое выведение чего-то - PowerShell - вещь красоты - и одна из ее самых сильных сторон. Например, общий Hello, World! приложение сводится к одной строке:
"Hello, World!"
Он создает строковый объект, назначает вышеупомянутое значение и является последним элементом в конвейере команд, который вызывает метод .toString()
и выводит результат на STDOUT
(по умолчанию). Вещь красоты.
Другие команды Write-*
специфичны для вывода текста в связанные потоки и имеют свое место как таковое.
Ответ 2
Думаю, в этом случае вам понадобится Write-Output.
Если у вас есть script как
Write-Output "test1";
Write-Host "test2";
"test3";
то, если вы вызываете script с перенаправленным выходом, что-то вроде yourscript.ps1 > out.txt
, вы получите test2
на экране test1\ntest3\n
в "out.txt".
Обратите внимание, что "test3" и строка Write-Output всегда добавят новую строку к вашему тексту, и в PowerShell нет способа остановить это (т.е. echo -n
невозможно в PowerShell с помощью собственных команд). Если вы хотите (несколько базовую и легкую в Bash) функциональность echo -n
, то см. ответ samthebest.
Если командный файл запускает команду PowerShell, он, скорее всего, захватит команду Write-Output. У меня были "длительные дискуссии" с системными администраторами о том, что должно быть написано на консоли, а что нет. Мы теперь согласились, что единственная информация, если script выполнена успешно или умерла, должна быть Write-Host
'ed, и все, что является script автором, возможно, должно знать о выполнении (какие элементы были обновлены, какие поля были установлены, и так далее) переходит к Write-Output. Таким образом, когда вы отправляете script системному администратору, он может легко runthescript.ps1 >someredirectedoutput.txt
и видеть на экране, если все в порядке. Затем отправьте "someredirectedoutput.txt" обратно разработчикам.
Ответ 3
Я думаю, что следующее - хорошая выставка Эха против Write-Host. Обратите внимание, как test() на самом деле возвращает массив целых чисел, а не единственное целое число, как можно легко поверить.
function test {
Write-Host 123
echo 456 # AKA 'Write-Output'
return 789
}
$x = test
Write-Host "x of type '$($x.GetType().name)' = $x"
Write-Host "'$x[0] = $($x[0])"
Write-Host "'$x[1] = $($x[1])"
Терминал вышеупомянутого:
123
x of type 'Object[]' = 456 789
$x[0] = 456
$x[1] = 789
Ответ 4
Вы можете использовать любой из них в своем сценарии, поскольку они пишут потоки по умолчанию (вывод и ошибка). Если вы отправляете вывод на другой командный файл, вы хотели бы использовать "Write-Output" , который в конечном итоге завершится в Write-Host.
В этой статье описываются различные параметры вывода: PowerShell O для вывода
Ответ 5
Вы просто не можете заставить PowerShell пропускать эти надоедливые символы перевода. Это не делает script или командлет.
Конечно, Write-Host - это абсолютная бессмыслица, потому что вы не можете перенаправлять/трубить с нее! Вам просто нужно написать свой собственный:
using System;
namespace WriteToStdout
{
class Program
{
static void Main(string[] args)
{
if (args != null)
{
Console.Write(string.Join(" ", args));
}
}
}
}
например.
PS C:\> writetostdout finally I can write to stdout like echo -n
finally I can write to stdout like echo -nPS C:\>
Ответ 6
Write-Host "Found file - " + $File.FullName -ForegroundColor Magenta
Magenta может быть одним из значений счетчика "System.ConsoleColor" - Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White.
+ $File.FullName
является необязательным и показывает, как поместить переменную в строку.
Ответ 7
Что было бы правильно использовать для записи в Windows эквивалента стандартного вывода?
По сути, но, к сожалению, и Windows PowerShell, и PowerShell Core начиная с v7.0 отправляют все свои 6 (!) выходных потоков на стандартный вывод, когда вызывается извне, через PowerShell CLI.
См. эту проблему GitHub для обсуждения этого проблемного поведения, которое, скорее всего, не будет исправлено ради обратной совместимости.
На практике это означает, что любой поток PowerShell, в который вы отправляете выходные данные, будет воспринят внешним абонентом как вывод stdout:
Например, если вы выполните следующее из cmd.exe
, вы не увидите выходных данных, потому что перенаправление stdout на NUL
в равной степени относится ко всем потокам PowerShell:
C:\>powershell -noprofile -command "Write-Error error!" >NUL
Однако - что любопытно - если вы перенаправляете stderr, PowerShell отправляет свой поток ошибок на stderr, так что с помощью 2>
вы можете выборочно перехватывать выходные данные потока ошибок; следующие выходные данные просто 'hi'
- вывод потока успеха - при захвате вывода потока ошибок в файл err.txt
:
C:\>powershell -noprofile -command "'hi'; Write-Error error!" 2>err.txt
желаемое поведение :
- Отправьте PowerShell успешный выходной поток (номер
1
) на стандартный вывод.
Отправлять выходные данные из всех других потоков в stderr, который является единственной опцией, учитывая, что между процессами существует только 2 выходных потока: stdout (стандартный вывод) для данных и stderr (стандартная ошибка) для сообщений об ошибках и все другие типы сообщений - например, информация о состоянии - которые не являются данными.
Желательно сделать это различие в вашем коде, даже если в настоящее время оно не соблюдается.
Внутри PowerShell:
Write-Host
- это для вывода на дисплей, и обходит поток вывода успешных результатов - поэтому его вывод нельзя ни (непосредственно) захватить в переменной, ни подавить, ни перенаправить.
Его первоначальная цель состояла в том, чтобы просто создать обратную связь с пользователем и создать простые консольные пользовательские интерфейсы (цветной вывод).
Из-за предыдущей невозможности захвата или перенаправления PowerShell версии 5 сделал Write-Host
вновь введенным информационным потоком (номер 6
), поэтому с тех пор можно захватывать и перенаправлять вывод Write-Host
.
Write-Error
предназначен для записи нескончаемых ошибок в поток ошибок (номер 2
); концептуально поток ошибок является эквивалентом stderr.
Write-Output
пишет в поток success [output] (число 1
), что концептуально эквивалентно stdout; это поток для записи данных (результатов) в.
- Однако явное использование
Write-Output
редко требуется из-за функции неявного вывода PowerShell:
- Вывод любой команды или выражения, которые явно не захвачены, не подавлены и не перенаправлены, автоматически отправляются в поток успеха; например,
Write-Output "Honey, I'm $HOME"
и "Honey, I'm $HOME"
эквивалентны, причем последние не только более краткие, но и более быстрые.
Ответ 8
Используйте внешнюю программу, как изнутри PowerShell script:
cmd /c echo "Long string: $LongStr"
Это глупо и дорого с точки зрения запуска отдельного процесса, но PowerShell плохо разработан.