Як вивести щось у PowerShell


210

Я запускаю скрипт PowerShell з пакетного файлу. Сценарій отримує веб-сторінку і перевіряє, чи є вміст сторінки рядком "ОК".

Сценарій PowerShell повертає рівень помилки до пакетного сценарію.

Пакетний сценарій виконується програмою автоматизації FTP ScriptFTP . Якщо виникла помилка, я можу змусити ScriptFTP надіслати повний вихід консолі адміністратору через E-Mail.

У сценарії PowerShell я хотів би вивести повернене значення з веб-сайту, якщо це не "ОК", тому повідомлення про помилку потрапляє у вихідний консоль, а отже, у пошту стану.

Я новачок у PowerShell і не впевнений, яку функцію виводу використовувати для цього. Я бачу три:

  • Пишіть-приймаюче
  • Запис-вихід
  • Помилка запису

Що було б правильно використовувати для запису в еквівалент Windows stdout?

Відповіді:


196

Просто випустити щось PowerShell - справа краси - і одна з його найбільших сильних сторін. Наприклад, загальний привіт, світ! додаток зведено до одного рядка:

"Hello, World!"

Він створює об'єкт рядка, призначає вищезгадане значення і, будучи останнім елементом у конвеєрі команд, він викликає .toString()метод і виводить результат STDOUT(за замовчуванням). Справа краси.

Інші Write-*команди характерні для виведення тексту в пов'язані з ними потоки і мають своє місце як таке.


9
Це насправді не відбувається. Це рядковий буквальний вираз і єдине, що є в його конвеєрі. Таким чином, це рівнозначно "Hello, World!" | Out-Host. Out-Hostз іншого боку, відправляє об'єкти на хост PowerShell для відображення, і його реалізація залежить від хоста. Хост консолі посилає їх до стандартної вихідної ручки (проходить Out-Defaultпо дорозі). PowerShell ISE відображає їх на своїй вихідній панелі, проте інші хости можуть виконувати ще цілі речі.
Джої

5
Об'єкти також не перетворюються сліпо на рядок, а проходять через формат, який вирішує, що з ними робити. Тому, наприклад, ви бачите Get-ChildItem, що вихідні дані надходять у формі таблиці, і результати мають багато властивостей (наприклад, WMI) за замовчуванням Format-List.
Joey

120

Я думаю, що в цьому випадку вам знадобиться Write-Output .

Якщо у вас є такий сценарій, як

Write-Output "test1";
Write-Host "test2";
"test3";

тоді, якщо ви зателефонуєте на скрипт із перенаправленим висновком, щось подібне yourscript.ps1 > out.txt, ви з’явитесь test2на екрані test1\ntest3\nу "out.txt".

Зауважте, що "test3" і рядок Write-Output завжди додадуть новий текст до вашого тексту, і в PowerShell немає можливості зупинити це (тобто echo -nнеможливо в PowerShell з нативними командами). Якщо ви хочете (дещо базовий і простий у Bash ) функціональність, echo -nто дивіться відповідь samthebest .

Якщо пакетний файл виконує команду PowerShell, він, швидше за все, захопить команду Write-Output. У мене були "довгі дискусії" з адміністраторами системи про те, що слід писати на консоль, а що не слід. Зараз ми домовились, що єдина інформація, якщо сценарій успішно виконаний або загинув, повинна бути Write-Hostвідредагована, і все, що є автором сценарію, може знати про виконання (які пункти були оновлені, які поля були встановлені тощо) на запис-вихід. Таким чином, коли ви подаєте сценарій системному адміністратору, він може легко runthescript.ps1 >someredirectedoutput.txtі побачити на екрані, якщо все в порядку. Потім відправте "someredirectedoutput.txt" назад розробникам.


9

Я думаю, що наступне є хорошим експонатом Echo vs. Write-Host . Зверніть увагу, як test () насправді повертає масив ints, а не один int, як можна було б легко повірити.

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

Я можу це дивитись цілий день ... Але чому $x = testтільки друк, 123а не також 456?
not2qubit

7

Ви можете використовувати будь-яке з них у своєму сценарії, оскільки вони записують у потоки за замовчуванням (вихід та помилка). Якщо ви працювали з іншим командлетом, ви хочете використовувати Write-Output , який згодом закінчиться в Write-Host .

У цій статті описані різні параметри виводу: PowerShell O призначений для виводу


1
Дякуємо за посилання Боже, це складно . Якщо хост Write - це якась функція кінцевої точки або промивки, я спробую перейти до цього і повідомити про це.
Pekka

3
Write-Host "Found file - " + $File.FullName -ForegroundColor Magenta

Magenta може бути одним із значень переліку "System.ConsoleColor" - чорний, темний темний, темний екран, темний сірий, темний червоний, темний магента, темний жовтий, сірий, темногрий, синій, зелений, блакитний, червоний, пурпурний, жовтий, білий.

Параметр + $File.FullNameнеобов’язковий і показує, як ввести змінну в рядок.


2

Ви просто не можете змусити PowerShell опустити ці примхливі рядки. Немає сценарію чи командлета, який би це робив.

Звичайно, 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:\>

Ви могли це зробити в самому корпусі. [System.Console] :: Write ("stringy") Однак ви не зможете перенаправляти це взагалі в shellhell.
Ніколі

1
Звичайно, ти можеш. Дивіться це запитання
Slogmeister Extraordinaire

1

Що було б правильно використовувати для запису в еквівалент stdout в Windows?

В силі , але дуже , до жаль , як Windows PowerShell і PowerShell ядро від v7.0, відправити всі їх 6 (!) Вихідні потоки в стандартний висновок , коли називаються ззовні , з допомогою PowerShell в CLI .

  • Дивіться цей випуск GitHub для обговорення цієї проблематичної поведінки, яка, ймовірно, не виправиться заради зворотної сумісності.

  • На практиці це означає, що незалежно від потоку PowerShell, на який ви надсилаєте вихід, зовнішній абонент буде сприйматися як висновок stdout :

    • Наприклад, якщо запустити наступне з cmd.exe, ви не побачите жодного результату, оскільки перенаправлення stdout NULзастосовується однаково для всіх потоків PowerShell:

      • C:\>powershell -noprofile -command "Write-Error error!" >NUL
    • Однак - цікаво - якщо ви перенаправити потік помилок , PowerShell робить відправити свій потік помилок в стандартний потік помилок , так що з 2>ви можете перехоплювати висновок помилок потоку вибірково; наступні виходи просто 'hi'- результат успішного потоку - під час фіксації виходу потоку помилок у файл err.txt:

      • C:\>powershell -noprofile -command "'hi'; Write-Error error!" 2>err.txt

Бажано поведінкою є:

  • Надішліть вихідний потік PowerShell (номер ) на stdout1 .
  • Надіслати вихід з усіх інших потоків на stderr , що є єдиним варіантом, враховуючи, що між процесами існує лише 2 вихідних потоки - stdout (стандартний вихід) для даних та stderr (стандартна помилка) для повідомлень про помилки та всіх інших типів повідомлень - таких як інформацію про стан - це не дані .

  • Доцільно вносити це відмінність у свій код, навіть якщо він наразі не дотримується .


Всередині PowerShell :

  • Write-Hostє для відображення виводу , і обходить вихідний потік успіху - як такої, його вихід не може бути ні (безпосередньо) захоплені в змінної , ні придушене , ні перенаправлені.

    • Його первісний намір полягав у тому, щоб просто створити відгуки користувачів та створити прості, консольні інтерфейси користувача (кольоровий вихід).

    • З - за неможливості попередніх бути захоплені або перенаправлений, PowerShell версії 5 , виконана Write-Hostз зновувведенням потоком інформації (число 6), так що з тих пір це можна захоплювати і перенаправляти Write-Hostвисновок.

  • Write-Errorпризначений для запису непотокових помилок у потік помилок (число 2); концептуально потік помилок є еквівалентом stderr.

  • Write-Outputзаписує в потік ( вихід) потік (число 1), який концептуально еквівалентний stdout; це потік для запису даних (результатів) в.

    • Однак явне використання цього Write-Outputрідко потрібне через неявну вихідну функцію PowerShell :
      • Виведення з будь-якої команди чи вираження, які явно не захоплені, придушені чи перенаправлені, автоматично надсилається в потік успіху ; наприклад, Write-Output "Honey, I'm $HOME"і "Honey, I'm $HOME"є рівнозначними, при цьому останні не тільки більш стислі, але й швидші.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.