Аналоги > и >> в PowerShell
Если вы знакомы с операторами командной строки Linux, то вы можете знать, что оператор «>» перенаправляет вывод в файл, если файл существует, то он перезаписывается, если файл не существует, то он создаётся и в него записывается содержимое.
В PowerShell этот оператор также работает, например, в следующей команде результат работы командлета будет сохранён в файл man.txt:
Get-Help about_Comparison_Operators -Full > man.txt
В Linux существует ещё один оператор для перенаправления стандартного вывода, это «>>», который работает аналогично предыдущему, но если файл уже существует, то вместо перезаписи, новые данные дописываются в файл, например, следующая команда допишет выводом командлета содержимое файла man.txt, а если его нет, то создаст этот файл:
Get-Help about_Comparison_Operators -Full >> man.txt
В PowerShell вы можете использовать «>» и «>>» если вам достаточно простого перенаправления вывода в файл. Также имеется командлет Out-File который кроме выполнения перенаправления вывода имеет дополнительную функциональность.
Перенаправление вывода в PowerShell
По умолчанию PowerShell отправляет выходные данные своей команды в консоль PowerShell. Однако вы можете направить вывод в текстовый файл, и вы можете перенаправить вывод ошибок в обычный поток вывода.
Для перенаправления вывода можно использовать следующие методы:
- Использовать командлет Out-File, который отправляет выходные данные команды в текстовый файл. Как правило, вы используете командлет Out-File когда вам нужно использовать его параметры, такие как параметры -Encoding, -Force, -Width или -NoClobber.
- Использовать командлет Tee-Object, который отправляет вывод команды в текстовый файл, а затем отправляет его в конвейер.
- Использовать операторы перенаправления PowerShell.
Операторы перенаправления PowerShell
Операторы перенаправления позволяют отправлять потоки данных в файл или выходной поток SUCCESS.
Операторы перенаправления PowerShell используют следующие числа для представления доступных выходных потоков:
№ потока | Описание | Представлен в |
---|---|---|
1 | SUCCESS Stream | PowerShell 2.0 |
2 | ERROR Stream | PowerShell 2.0 |
3 | WARNING Stream | PowerShell 3.0 |
4 | VERBOSE Stream | PowerShell 3.0 |
5 | DEBUG Stream | PowerShell 3.0 |
6 | INFORMATION Stream | PowerShell 5.0 |
* | All Streams | PowerShell 3.0 |
[!ПРИМЕЧАНИЕ] В PowerShell также есть поток PROGRESS, но он не используется для перенаправления.
Ниже перечислены операторы перенаправления PowerShell, где n представляет номер потока. Поток SUCCESS (1) используется по умолчанию, если поток не указан.
Оператор | Описание | Синтаксис |
---|---|---|
> | Отправить указанный поток в файл. | n> |
>> | ДОБАВИТЬ указанный поток к файлу. | n>> |
>&1 | _Перенаправляет_ указанный поток в поток SUCCESS. | n>&1 |
[!ПРИМЕЧАНИЕ] В отличие от некоторых оболочек Unix, вы можете перенаправлять другие потоки только в поток SUCCESS.
Примеры:
Пример 1: Перенаправление ошибок и вывод в файл
dir 'C:', 'fakepath' 2>&1 > .dir.log
В этом примере dir запускается для двух элементов, один из который завершится успешно, а для другого — с ошибкой.
Он использует «2>&1» для перенаправления потока ERROR в поток SUCCESS и «>» для отправки результирующего потока SUCCESS в файл с именем dir.log.
Пример 2: Отправить все данные потока SUCCESS в файл
.script.ps1 > script.log
Эта команда отправляет все данные потока SUCCESS в файл с именем script.log.
Пример 3. Отправка потоков Success, Warning и Error в файл
&{ Write-Warning "hello" Write-Error "hello" Write-Output "hi" } 3>&1 2>&1 > P:Tempredirection.log
В этом примере показано, как можно комбинировать операторы перенаправления для достижения желаемого результата.
- 3>&1 перенаправляет поток WARNING в поток SUCCESS.
- 2>&1 перенаправляет поток ERROR в поток SUCCESS (который теперь также включает все данные потока WARNING)
- > перенаправляет поток SUCCESS (который теперь содержит потоки WARNING и ERROR) в файл с именем C:tempredirection.log)
Пример 4: Перенаправить все потоки в файл
.script.ps1 *> script.log
В этом примере все потоки выводятся из сценария с именем script.ps1 в файл с именем script.log.
Пример 5: Подавить все данные Write-Host и Information Stream
&{ Write-Host "Hello" Write-Information "Hello" -InformationAction Continue } 6> $null
В этом примере подавляются все данные Information Stream (информационного потока). Дополнительные сведения о командлетах потока INFORMATION смотрите разделах Write-Host и Write-Information.
Смотрите также: Аналог echo в PowerShell
Примечания:
1. Операторы перенаправления, которые не добавляют данные (> и n>), перезаписывают текущее содержимое указанного файла без предупреждения.
2. Однако, если файл доступен только для чтения, является скрытым или системным файлом, перенаправление ТЕРПИТ НЕУДАЧУ. Операторы перенаправления добавления (>> и n>>) не записывают в файл, доступный только для чтения, но они добавляют содержимое в системный или скрытый файл.
3. Чтобы принудительно перенаправить содержимое в доступный только для чтения, скрытый или системный файл, используйте командлет Out-File с его параметром -Force.
4. Когда вы пишете в файлы, операторы перенаправления используют кодировку Unicode. Если файл имеет другую кодировку, выходные данные могут быть отформатированы неправильно. Чтобы перенаправить содержимое в файлы, отличные от Unicode, используйте командлет Out-File с его параметром -Encoding.
5. Возможная путаница с операторами сравнения
Оператор «>» не следует путать с оператором сравнения Больше (часто обозначается как «>» в других языках программирования).
В зависимости от сравниваемых объектов вывод с использованием «>» может показаться правильным (поскольку 36 не больше 42).
if (36 > 42) { "true" } else { "false" } false
Однако проверка локальной файловой системы позволяет увидеть, что был создан файл с именем 42, а в него записано содержимое 36.
dir Mode LastWriteTime Length Name ---- ------------- ------ ---- ------ 1/02/20 10:10 am 3 42 cat 42 36
Попытка использовать обратное сравнение «<» (меньше чем) приводит к системной ошибке:
if (36 < 42) { "true" } else { "false" } At line:1 char:8 + if (36 < 42) { "true" } else { "false" } + ~ The '<' operator is reserved for future use. + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : RedirectionNotSupported
Если требуется числовое сравнение, следует использовать -lt и -gt.
Смотрите также: Операторы сравнения в PowerShell
Как в PowerShell дописать вывод в файл
Итак, оператор «>» перенаправляет вывод, который в противном случае попал бы на экран, в файл. Этот оператор полностью переписывает файл, если он уже существует.
Для того, чтобы вместо замены содержимого файла дописать в него, можно использовать оператор «>>»:
Get-Help about_Comparison_Operators -Full >> man.txt
Командлет Out-File для сохранение в файл в PowerShell
Командлет Out-File отправляет вывод в файл. Когда вам нужно указать параметры для вывода, используйте Out-File вместо оператора перенаправления («>»).
Как дописать файл. Аналог «>>» в Out-File
Для того, чтобы добавить вывод в конец существующего файла (вместо его перезаписи), используйте в вашей команде опцию -Append.
Как указать кодировку
Для изменения кодировки по умолчанию, используйте опцию «-Encoding КОДИРОВКА». Кодировкой по умолчанию является UTF8NoBOM.
Опция -Encoding задаёт тип кодировки для целевого файла. Значение по умолчанию — UTF8NoBOM. Кодировка — это динамический параметр, который поставщик FileSystem добавляет в Set-Content. Этот параметр работает только на дисках с файловой системой. Допустимые значения этого параметра следующие:
- ASCII: использует кодировку для набора символов ASCII (7-бит).
- BigEndianUnicode: кодирует в формате UTF-16, используя порядок байтов с прямым порядком байтов.
- OEM: использует кодировку по умолчанию для MS-DOS и консольных программ.
- Unicode: кодируется в формате UTF-16 с использованием порядка байтов с прямым порядком байтов.
- UTF7: кодирует в формате UTF-7.
- UTF8: кодирует в формате UTF-8.
- UTF8BOM: кодирует в формате UTF-8 с меткой порядка байтов (BOM)
- UTF8NoBOM: кодирует в формате UTF-8 без метки порядка байтов (BOM)
- UTF32: кодирует в формате UTF-32.
Начиная с PowerShell 6.2, параметр -Encoding также позволяет использовать числовые идентификаторы зарегистрированных кодовых страниц (например, «-Encoding 1251») или строковые имена зарегистрированных кодовых страниц (например, «-Encoding «windows-1251»».
Как указать путь до файла
Обязательным аргументом командлета Out-File является путь до файла в который будет сделано сохранение выводимых данных. Вы можете указать его с опцией -FilePath, либо опустить эту опцию и указать путь до файла без неё.
Обратите внимание, что вы не можете использовать подстановочные знаки в пути до файла.
Смотрите также: Подстановочные символы в PowerShell
Как переписать файл только для чтения
С помощью опции -Force вы можете переопределить атрибут только для чтения и перезаписать существующий файл, доступный только для чтения. Параметр -Force не отменяет ограничения безопасности, то есть если у вас нет прав на записи в указываемый файл, то вы всё равно не сможете записать в него..
Как не добавлять символ новой строки (newline) в конец файла
При записи в файл, в конец будет добавлен символ перехода на новую строку. То есть если в файл будут добавлены другие данные, то они будут записаны с новой строки. Если вы не хотите, чтобы добавлялся символ новой строки, то используйте опцию -NoNewline. Если для формирования вывода используется несколько строк, то по умолчанию они разделяются пробелом, эта опция также отменяет вставку пробелов между строк.
Как запретить перезаписывать существующий файл
Опция -NoClobber предотвращает перезапись существующего файла и отображает сообщение о том, что файл уже существует. По умолчанию, если файл существует по указанному пути, Out-File перезаписывает файл без предупреждения.
Что может быть вводом командлета Out-File
В Out-File вы можете отправить по конвейеру любые объекты, а не только строки (как например в Set-Content и Add-Content). Например, следующая команда сохраняет практически пустой файл:
Get-ComputerInfo | Set-Content test3.txt
Но с помощью Out-File весь вывод будет сохранён в файл:
Get-ComputerInfo | Out-File test4.txt
Командлеты типа Out- не форматируют объекты; они просто визуализируют их и отправляют в указанное место отображения. Если вы отправляете неформатированный объект командлету Out-, этот командлет отправляет его командлету форматирования перед его визуализацией.
Чтобы отправить вывод команды PowerShell командлету Out-File, используйте конвейер. Вы можете хранить данные в переменной и использовать параметр -InputObject для передачи данных в командлет Out-File.
Out-File отправляет данные, но не создаёт никаких объектов вывода. Если вы направите вывод Out-File в Get-Member, командлет Get-Member сообщает, что объекты не были указаны.
Пример 1: Отправить вывод и создать файл
Get-Process | Out-File -FilePath .Process.txt Get-Content -Path .Process.txt NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName ------ ----- ----- ------ -- -- ----------- 29 22.39 35.40 10.98 42764 9 Application 53 99.04 113.96 0.00 32664 0 CcmExec 27 96.62 112.43 113.00 17720 9 Code
Командлет Get-Process получает список процессов, запущенных на локальном компьютере. Объекты Process отправляются по конвейеру в командлет Out-File. Затем Out-File использует параметр -FilePath и создаёт файл с именем Process.txt в текущем каталоге. Команда Get-Content получает содержимое из файла и отображает его в консоли PowerShell.
Пример 2: Предотвратить перезапись существующего файла
Get-Process | Out-File -FilePath .Process.txt -NoClobber Out-File : The file 'C:TestProcess.txt' already exists. At line:1 char:15 + Get-Process | Out-File -FilePath .Process.txt -NoClobber + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Командлет Get-Process получает список процессов, запущенных на локальном компьютере. Объекты Process отправляются по конвейеру в командлет Out-File. Затем Out-File использует параметр -FilePath и пытается выполнить запись в файл в текущем каталоге с именем Process.txt. Параметр -NoClobber предотвращает перезапись файла и отображает сообщение о том, что файл уже существует.
Пример 3: Сохранение вывода в файл в кодировке ASCII
$Procs = Get-Process Out-File -FilePath .Process.txt -InputObject $Procs -Encoding ASCII -Width 50
Командлет Get-Process получает список процессов, запущенных на локальном компьютере. Объекты процесса хранятся в переменной $Procs. Затем Out-File использует параметр -FilePath и создаёт файл с именем Process.txt в текущем каталоге. Параметр -InputObject передаёт объекты с процессами из $Procs в файл Process.txt. Параметр -Encoding преобразует вывод в формат ASCII. Параметр -Width ограничивает каждую строку в файле 50 символами, поэтому некоторые данные могут быть усечены.
Пример 4: Использование провайдера и отправка вывода в файл
Set-Location -Path Alias: Get-Location Path ---- Alias: Get-ChildItem | Out-File -FilePath C:TestDirAliasNames.txt Get-Content -Path C:TestDirAliasNames.txt CommandType Name ----------- ---- Alias % -> ForEach-Object Alias ? -> Where-Object Alias ac -> Add-Content Alias cat -> Get-Content
Команда Set-Location использует параметр -Path для установки текущего местоположения провайдера реестра «Alias:». Командлет Get-Location отображает полный путь к «Alias:». Get-ChildItem отправляет объекты по конвейеру командлету Out-File. Out-File использует параметр -FilePath, чтобы указать полный путь и имя файла для вывода, C:TestDirAliasNames.txt. Командлет Get-Content использует параметр -Path и отображает содержимое файла в консоли PowerShell.
Связанные статьи:
- Решение проблем с кодировкой вывода в PowerShell и сторонних утилитах, запущенных в PowerShell (100%)
- Ошибки «Оператор «<» зарезервирован для использования в будущем» и «The ‘<‘ operator is reserved for future use.» (РЕШЕНО) (100%)
- Аналог echo в PowerShell (56%)
- Как в PowerShell менять набор выводимых по умолчанию данных (56%)
- Как выводить данные без таблицы в PowerShell (56%)
- Командлеты Set-Content и Add-Content для обработки строк (RANDOM — 50%)
description | Locale | ms.date | online version | schema | title |
---|---|---|---|---|---|
Explains how to redirect output from PowerShell to text files. |
en-US |
05/04/2021 |
https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-7.2&WT.mc_id=ps-gethelp |
2.0.0 |
about Redirection |
Short description
Explains how to redirect output from PowerShell to text files.
Long description
By default, PowerShell sends output to the PowerShell host. Usually this is the
console application. However, you can redirect the output to a text file and you
can redirect error output to the regular output stream.
You can use the following methods to redirect output:
-
Use the
Out-File
cmdlet, which sends command output to a text file.
Typically, you use theOut-File
cmdlet when you need to use its parameters,
such as theEncoding
,Force
,Width
, orNoClobber
parameters. -
Use the
Tee-Object
cmdlet, which sends command output to a text file and
then sends it to the pipeline. -
Use the PowerShell redirection operators. Using the redirection operator with
a file target is functionally equivalent to piping toOut-File
with no
extra parameters.
For more information about streams, see
about_Output_Streams.
Redirectable output streams
PowerShell supports redirection of the following output streams.
Stream # | Description | Introduced in | Write Cmdlet |
---|---|---|---|
1 | Success Stream | PowerShell 2.0 | Write-Output |
2 | Error Stream | PowerShell 2.0 | Write-Error |
3 | Warning Stream | PowerShell 3.0 | Write-Warning |
4 | Verbose Stream | PowerShell 3.0 | Write-Verbose |
5 | Debug Stream | PowerShell 3.0 | Write-Debug |
6 | Information Stream | PowerShell 5.0 | Write-Information , Write-Host |
* | All Streams | PowerShell 3.0 |
There is also a Progress stream in PowerShell, but it does not support
redirection.
[!IMPORTANT]
The Success and Error streams are similar to the stdout and stderr
streams of other shells. However, stdin is not connected to the PowerShell
pipeline for input.
PowerShell redirection operators
The PowerShell redirection operators are as follows, where n
represents
the stream number. The Success stream ( 1
) is the default if no stream
is specified.
Operator | Description | Syntax |
---|---|---|
> |
Send specified stream to a file. | n> |
>> |
Append specified stream to a file. | n>> |
>&1 |
Redirects the specified stream to the Success stream. | n>&1 |
[!NOTE]
Unlike some Unix shells, you can only redirect other streams to the
Success stream.
Examples
Example 1: Redirect errors and output to a file
This example runs dir
on one item that will succeed, and one that will error.
dir 'C:', 'fakepath' 2>&1 > .dir.log
It uses 2>&1
to redirect the Error stream to the Success stream, and
>
to send the resultant Success stream to a file called dir.log
Example 2: Send all Success stream data to a file
This example sends all Success stream data to a file called script.log
.
.script.ps1 > script.log
Example 3: Send Success, Warning, and Error streams to a file
This example shows how you can combine redirection operators to achieve a
desired result.
&{ Write-Warning "hello" Write-Error "hello" Write-Output "hi" } 3>&1 2>&1 > C:Tempredirection.log
3>&1
redirects the Warning stream to the Success stream.2>&1
redirects the Error stream to the Success stream (which also
now includes all Warning stream data)>
redirects the Success stream (which now contains both Warning
and Error streams) to a file calledC:tempredirection.log
)
Example 4: Redirect all streams to a file
This example sends all streams output from a script called script.ps1
to a
file called script.log
.script.ps1 *> script.log
Example 5: Suppress all Write-Host and Information stream data
This example suppresses all information stream data. To read more about
Information stream cmdlets, see
Write-Host and
Write-Information
&{ Write-Host "Hello" Write-Information "Hello" -InformationAction Continue } 6> $null
Example 6: Show the effect of Action Preferences
Action Preference variables and parameters can change what gets written to a
particular stream. The script in this example shows how the value of
$ErrorActionPreference
affects what gets written to the Error stream.
$ErrorActionPreference = 'Continue' $ErrorActionPreference > log.txt get-item /not-here 2>&1 >> log.txt $ErrorActionPreference = 'SilentlyContinue' $ErrorActionPreference >> log.txt get-item /not-here 2>&1 >> log.txt $ErrorActionPreference = 'Stop' $ErrorActionPreference >> log.txt Try { get-item /not-here 2>&1 >> log.txt } catch { "`tError caught!" >> log.txt } $ErrorActionPreference = 'Ignore' $ErrorActionPreference >> log.txt get-item /not-here 2>&1 >> log.txt $ErrorActionPreference = 'Inquire' $ErrorActionPreference >> log.txt get-item /not-here 2>&1 >> log.txt $ErrorActionPreference = 'Continue'
When we run this script we get prompted when $ErrorActionPreference
is set to
Inquire
.
PS C:temp> .test.ps1 Confirm Cannot find path 'C:not-here' because it does not exist. [Y] Yes [A] Yes to All [H] Halt Command [S] Suspend [?] Help (default is "Y"): H Get-Item: C:temptest.ps1:23 Line | 23 | get-item /not-here 2>&1 >> log.txt | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | The running command stopped because the user selected the Stop option.
When we examine the log file we see the following:
PS C:temp> Get-Content .log.txt
Continue
Get-Item: C:temptest.ps1:3
Line |
3 | get-item /not-here 2>&1 >> log.txt
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Cannot find path 'C:not-here' because it does not exist.
SilentlyContinue
Stop
Error caught!
Ignore
Inquire
Notes
The redirection operators that do not append data (>
and n>
) overwrite the
current contents of the specified file without warning.
However, if the file is a read-only, hidden, or system file, the redirection
fails. The append redirection operators (>>
and n>>
) do not write to a
read-only file, but they append content to a system or hidden file.
To force the redirection of content to a read-only, hidden, or system file,
use the Out-File
cmdlet with its Force
parameter.
When you are writing to files, the redirection operators use UTF8NoBOM
encoding. If the file has a different encoding, the output might not be
formatted correctly. To write to files with a different encoding, use the
Out-File
cmdlet with its Encoding
parameter.
Width of output when writing to a file
When you are writing to a file using either Out-File
or the redirection
operators, PowerShell formats table output to the file based on the width of
the console it is running within. For instance, when logging table output
to file using a command like Get-ChildItem Env:Path > path.log
on a system
where the console width is set to 80 columns, the output in the file is
truncated to 80 characters:
Name Value
---- -----
Path C:Program FilesPowerShell7;C:WINDOWS…
Considering that the console width may be set arbitrarily on systems where
your script is run, you may prefer that PowerShell format table output to
files based on a width that you specify instead.
The Out-File
cmdlet provides a Width parameter that allows you to set
the width you would like for table output. Rather than having to add
-Width 2000
everywhere you invoke Out-File
, you can use the
$PSDefaultParameterValues
variable to set this value for all usages of the
Out-File
cmdlet in a script. And since the redirection operators (>
and
>>
) are effectively aliases for Out-File
, setting the Out-File:Width
parameter for the whole script impacts the formatting width for the
redirection operators as well. Put the following command near the top of your
script to set Out-File:Width
for the whole script:
$PSDefaultParameterValues['out-file:width'] = 2000
Increasing the output width will increase memory consumption when logging
table formatted output. If you are logging a lot of tabular data to file and
you know you can get by with a smaller width, use the smaller width.
In some cases, such as Get-Service
output, in order to use the extra width
you will need to pipe the output through Format-Table -AutoSize
before
outputting to file.
$PSDefaultParameterValues['out-file:width'] = 2000 Get-Service | Format-Table -AutoSize > services.log
For more information about $PSDefaultParameterValues
, see
about_Preference_Variables.
Potential confusion with comparison operators
The >
operator is not to be confused with the
Greater-than comparison
operator (often denoted as >
in other programming languages).
Depending on the objects being compared, the output using >
can appear to be
correct (because 36 is not greater than 42).
PS> if (36 > 42) { "true" } else { "false" } false
However, a check of the local filesystem can see that a file called 42
was
written, with the contents 36
.
PS> dir Mode LastWriteTime Length Name ---- ------------- ------ ---- ------ 1/02/20 10:10 am 3 42 PS> cat 42 36
Attempting to use the reverse comparison <
(less than), yields a system error:
PS> if (36 < 42) { "true" } else { "false" } ParserError: Line | 1 | if (36 < 42) { "true" } else { "false" } | ~ | The '<' operator is reserved for future use.
If numeric comparison is the required operation, -lt
and -gt
should be
used. For more information, see the -gt
operator in
about_Comparison_Operators.
See also
- about_Command_Syntax
- about_Operators
- about_Output_Streams
- about_Path_Syntax
- Out-File
- Tee-Object
- Write-Debug
- Write-Error
- Write-Host
- Write-Information
- Write-Output
- Write-Progress
- Write-Verbose
- Write-Warning
Всем привет.
В предыдущих двух постах были подробно изложены методы отлова критических и некритических ошибок при работе с PowerShell. Но я решил что будет несправедливым не отметить самые основные моменты, которые возникают в работе если что-то пошло не так. Т.е. переменные и обьекты в PowerShell которые содержат первичную информацию о работе нашего скрипта. Речь пойдет об объекте ErrorRecord, о переменной $Error, о мониторинге возникновения ошибки c помощью переменной $? и кодов возврата, а также упомянем командлет Set-PSDebug и точки прерывания. Поможет нам в этом замечательная книга Попова А. В. «Введение в Windows PowerShell» — СПб.: БХВ-Петербург, 2009.
Поехали.
1. Объект ErrorRecord и поток ошибок.
В PowerShell информация о возникающих ошибках записывается в поток ошибок, который по умолчанию отображается на экране, например:
PS C:> dir «C:Folder doesn’t exist»
Get-ChildItem : Не удается найти путь «C:Folder doesn’t exist»,
так как он не существует.
В строка:1 знак:4
+ dir <<<< «C:Folder doesn’t exist»
Поток ошибок можно перенаправить в текстовый файл с помощью специального оператора 2>, например:
PS C:> dir «C:Folder doesn’t exist» 2>err.txt
Проверим теперь содержимое файла err.txt:
PS C:> Get-Content err.txt
Get-ChildItem : Не удается найти путь «C:Folder doesn’t exist»,
так как он не существует.
В строка:1 знак:4
+ dir <<<< «Folder doesn’t exist» 2> err.txt
Как видите, в файл err.txt полностью записалось сообщение об ошибке, однако никакой дополнительной информации не появилось.
Где произошла ошибка смотрим так
PS C:> $err.InvocationInfo
MyCommand : Get-ChildItem
ScriptLineNumber : 1
OffsetInLine : -2147483648
ScriptName :
Line : $err = dir «C:Folder doesn’t exist» 2>&1
PositionMessage :
В строка:1 знак:11
+ $err = dir <<<< «C:Folder doesn’t exist» 2>&1
InvocationName : dir
PipelineLength : 1
PipelinePosition : 1
Хотя этот вывод даст нам место скрипта(или непсредственного ввода)
где ошибку интепретирует сама PowerShell, истинное место проблемы надо будет
искать самим.
2. Специальная переменная $Error.
В PowerShell имеется специальная переменная $Error, которая содержит коллекцию (массив) объектов ErrorRecord, соответствующих ошибкам, возникавшим в текущем сеансе работы. Максимальное количество элементов в данной коллекции задается значением переменной $MaximumErrorCount (по умолчанию это 256):
PS C:> $MaximumErrorCount
256
После заполнения массива $Error объекты для вновь возникающих ошибок будут заменять объекты, соответствующие старым ошибкам. Возникновение каждой новой ошибки приводит к смещению элементов в массиве $Error: объект для последней ошибки хранится в первом элементе ($Error[0]), объект для предыдущей ошибки — во втором элементе ($Error[1]) и т. д.
Убедимся, что элемент $Error[0] имеет тип ErrorRecord, и выведем содержимое этого элемента:
PS C:> $Error[0].GetType().FullName
System.Management.Automation.ErrorRecord
PS C:> $Error[0]
Get-ChildItem : Не удается найти путь «C:Несуществующий каталог»,
так как он не существует.
В строка:1 знак:4
+ dir <<<< «Несуществующий каталог»
Естественно, мы можем обращаться ко всем свойствам объекта ErrorRecord:
PS C:> $Error[0].Exception
Не удается найти путь «C:Несуществующий каталог», так как он не существует.
Повторим вывод свойства InvocationInfo
PS C:> $Error[0].InvocationInfo
MyCommand : Get-ChildItem
ScriptLineNumber : 1
OffsetInLine : -2147483648
ScriptName :
Line : $err = dir «C:Folder doesn’t exist» 2>&1
PositionMessage :
В строка:1 знак:11
+ $err = dir <<<< «C:Folder doesn’t exist» 2>&1
InvocationName : dir
PipelineLength : 1
PipelinePosition : 1
3. Мониторинг возникновения ошибки переменной $?.
В PowerShell имеется логическая переменная $?, которая равна $True, если последняя выполняемая операция завершена успешно, и $False, если во время выполнения последней
операции возникла ошибка. Такая же существует и в Linux.) Например, если выполнить командлет Get-Item для заведомо существующего каталога, то значение переменной $? будет равно $True:
PS C:> Get-Item С:
Каталог:
Mode LastWriteTime Length Name
—- ————- —— —-
d—hs 21.03.2016 12:00 C:
PS C:> $?
True
Если же выполнить этот же командлет для несуществующего каталога, то значение переменной $? будет равно $False:
PS C:> Get-Item С:321
Get-Item : Не удается найти путь «C:321», так как он не существует.
В строка:1 знак:9
Глава 9. Обработка ошибок и отладка 183
+ Get-Item <<<< С:321
PS C:> $?
False
4. Мониторинг возникновения ошибки по коду возврата.
Для внешних команд Windows и сценариев PowerShell определено понятие кода возврата (напомним, что для сценариев PowerShell этот код можно установить с помощью инструкции Exit). В операционной системе код возврата последней команды доступен через переменную среды %ERRORLEVEL%; в оболочке PowerShell данный код возврата хранится в специальной переменной $LASTEXITCODE. При этом, если код возврата равен нулю, то переменной $? присваивается значение $True. Если же код возврата не равен нулю, то считается, что при выполнении данной команды произошла ошибка, и переменной $? присваивается значение $False.
В качестве примера выполним команду интерпретатора cmd.exe, которая устанавливает нулевой код возврата. Для этого можно запустить cmd.exe с ключом /c (выполнить команду и завершить работу интерпретатора) и указать для исполнения команду exit 0:
PS C:> cmd /c exit 0
Проверим значения переменных $LASTEXITCODE и $?:
PS C:> $LASTEXITCODE
0
PS C:> $?
True
Теперь выполним команду интерпретатора cmd.exe с ненулевым кодом возврата (пусть, например, код возврата равен 10):
PS C:> cmd /c exit 10
Вновь проверим переменные $LASTEXITCODE и $?:
PS C:> $?
False
PS C:> $LASTEXITCODE
10
5. Командлет Set-PSDebug и точки прерывания.
Процесс поиска ошибок в сценариях неразрывно связан с отладкой. Поэтому нам стоит упомянуть что основным встроенным инструментом для отладки сценариев является командлет Set-PSDebug. Параметры этого командлета позволяют включить режимы трассировки и пошагового выполнения команд, а также режим обязательного объявления переменных:
-Trace 0 Отключение трассировки
-Trace 1 Включение основного режима трассировки
-Trace 2 Включение полного режима трассировки
-Step Включение режима пошагового выполнения
-Strict Включение режима обязательного объявления переменных
-Off Отключение всех механизмов отладки.
Примеры приводить не буду, назначение ключей очевидно из их названия. Самым интересным является режим пошагового выполнения -Step, который позволяет в любой момент вызвать вложенную командную строку для анализа или изменения состояния интерпретатора. Однако отлаживать более-менее большие сценарии с помощью данного метода часто оказывается неудобно, так как для запуска вложенного сеанса в определенной строке сценария придется каждый раз добираться до этой строки с самого начала сценария (каждую команду при этом
нужно выполнять, нажимая клавишу <A>).
Гораздо удобнее было бы использовать точки прерывания, позволяющие запускать сценарий в автоматическом режиме и приостанавливать выполнение на нужной команде. В PowerShell аналогом установки точки прерывания можно считать вызов метода $Host.EnterNestedPrompt(), например:
PS C:> for ($i=0; $i -lt 10; $i++) {
>> «i = $i»
>> if ($i -eq 5) {
>> «Моя точка прерывания»
>> $Host.EnterNestedPrompt()
>> }
>> }
>>
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
Моя точка прерывания
PS C:>>>
В данном примере на пятой итерации цикла выводится строка «Моя точка прерывания» и вызывается метод $Host.EnterNestedPrompt(). В результате выполнение цикла приостанавливается, и мы попадаем во вложенную командную строку (вид приглашения изменяется на >>>).
Выход из вложенного сеанса с помощью инструкции Exit:
PS C:>>> Exit
PS C:>
Вот так вот.
PowerShell has several redirection operators that can be used to redirect specific type of output to a file. For example, if you want to redirect all errors produced by different cmdlet in your script to a text file, you can use Error redirection to do so.
It is particularly helpful when you want to hide errors from appearing on the screen but need them to identify any possible issues and improving the script. Sometimes, when you have a script deployed in production, you can ask users (who are using your script) for the error redirection file to troubleshoot the script.
To send errors to specified file, use 2> file.name
To append errors to a specified file, use 2>> file.name
Following examples attempts to delete files from c:temp folder and redirects any errors to c:errors.txt file.
PS C:> Get-ChildItem -Path c:temp Directory: C:temp Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 4/24/2016 2:45 PM 972 errors.txt -a--- 4/24/2016 2:48 PM 21085 ex2.docx -a--- 4/24/2016 2:49 PM 274 test.txt -a--- 4/24/2016 2:47 PM 8008 test.xlsx -a--- 4/24/2016 2:49 PM 289 test2.ps1 PS C:> Get-ChildItem -Path C:temp | Remove-Item 2> C:errors.txt PS C:>
If above command has not resulted in any error, you will not see c:errors.txt or anything in the file. if the command produced any errors, it will be there in the error file. In example above, two documents were open and they were not deleted. notice how errors were not shown on the console but they were redirected to given error file:
PS C:> get-content C:errors.txt Remove-Item : Cannot remove item C:tempex2.docx: The process cannot access the file 'C:tempex2.docx' because it is being used by another process. At line:1 char:31 + Get-ChildItem -Path C:temp | Remove-Item 2> c:errors.txt + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : WriteError: (C:tempex2.docx:FileInfo) [Remove-Item], IOException + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand Remove-Item : Cannot remove item C:temptest.xlsx: The process cannot access the file 'C:temptest.xlsx' because it is being used by another process. At line:1 char:31 + Get-ChildItem -Path C:temp | Remove-Item 2> c:errors.txt + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : WriteError: (C:temptest.xlsx:FileInfo) [Remove-Item], IOException + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand PS C:> Get-ChildItem C:temp
Notice that the error message redirected to the file is same as you would see on the console when not handling (by means of -ErrorAction, Try/Catch etc.). It shows line number that has thrown the error and helps in troubleshooting the script/code.
2> c:errors.txt in Remove-Item cmdlet in the pipeline is used to direct the errors to given text file (here c:errors.txt). If you need to append to a file instead of overwriting/creating a new one (2> c:errors.txt creates the file if does not exist or overwrites it if it exist), use append operator (2>> c:errors.txt):
PS C:> Get-ChildItem -Path C:temp | Remove-Item 2>> c:errors.txt
One important point to note is, you shouldn’t always be just redirecting errors. There are times when you need to handle errors in a script and take appropriate action. In those cases, its better to use error handling (using try/catch, -ErrorAction parameter of supported cmdlets etc.) to handle the error appropriately.
The output of PowerShell commands is by default displayed in the terminal. But in some situations, it’s more useful to redirect the output to a file in PowerShell. For this, we are going to use the Out-File cmdlet.
There are different ways to output the results of a PowerShell script or command to file. It’s even possible to show the output in the terminal and export it to a file at the same time. And did you know that you can also export only the success, warning, or error results?
In this article
In this article, we are going to take a look at how to write the output to a file in PowerShell. I will also explain how you can append to an existing file or how you can create a log file.
There are a couple of ways to write the output of PowerShell to a file. The most common ways are to use the Out-File
cmdlet or the redirection operator >
. Other options are to use the Set-Content
and Add-Content
cmdlet. We are going to focus on the first two, but I will briefly mention the alternative if relevant.
The Out-File
cmdlet and redirect operator >
allows you to write and append (>>
) the PowerShell output to a file. The difference between the two is that the first accepts parameters and the latter doesn’t.
With the Out-File cmdlet we can use the following parameters:
Parameter | Description |
---|---|
-Filepath | Set the location and name of the file |
-Append | Append the output to the existing content of the file |
-Force | Overwrite a read-only file |
-NoClobber | Prevent overwrite of file |
-NoNewLine | No newline character will be written. |
-Width | Limit the number of characters on each line (default 80) |
-WhatIf | Run in test mode |
PowerShell Redirect Operator
The redirect operator however doesn’t have any parameters. But it has an advantage compared to Out-File. When using the Out-File cmdlet, only the successful results are exported, so warnings or errors won’t be written to the file.
When using the redirect operator we can specify which stream we want to export:
Operator | Description / Stream | Write cmdlet |
---|---|---|
> | Success only | Write-Output |
2> | Error only | Write-Error |
3> | Warning only | Write-Warning |
4> | Verbose only | Write-Verbose |
5> | Debug only | Write-Debug |
6> | Information only | Write-Information |
*> | All |
I will explain more about the different streams later, but let’s first take a look at how we can simply write the output to a file in PowerShell.
To write the output to a file all you have to do is pipe the Out-File
cmdlet behind your script or command and specify the path. If the file doesn’t exist, then it will be created by the cmdlet:
Get-Process -Name explorer | Out-File -FilePath c:tempprocess.txt # Same as: Get-Process -Name explorer > c:tempprocess.txt # The results Get-Content C:tempprocess.txt NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName ------ ----- ----- ------ -- -- ----------- 132 94,56 158,22 131,45 123364 1 explorer PS C:>
As you can see, the results of the Get-Process
cmdlet is stored in the process.txt file:
If you don’t specify any other parameter, then the Out-File cmdlet and redirect operator will overwrite any existing file by default. We can prevent this by adding the -NoClobber
parameter to the cmdlet
Get-Process -Name explorer | Out-File c:tempprocess.txt -NoClobber
Note that you can’t prevent overwriting with the redirect operator
If the file already exists, then an error will be thrown:
If you want to output to a file inside a script then I recommend that you use the Instead of overwriting, we can also append the output to the existing content of the file. For this, we can either use the You can also append to a non-existing file, both methods will create a new file if the specified file doesn’t exist. When appending output to an existing file the content will be placed on a new line. If you want to have the content on one single line, creating one long string, then you will need to use the Out-File cmdlet with the The newline character is placed after the value that you have added to the file. So it’s important to add the To make the result more readable I have added a semi-colon to all values. As you can see all the results are on the same line:Test-Path
cmdlet first to determine if the file already exists. This way you can write a better solution, like appending a date to the file name, instead of simply trying to write to it:$exportPath = "C:tempprocess.txt"
If (Test-Path $exportPath) {
# Show a warning or change the file name here
Write-Warning "File already exists"
$exportPath = "C:tempprocess-1.txt" # create something nice with a date or timestamp
}else{
Get-Process -Name explorer | Out-File $exportPath -NoClobber
}
PowerShell Append to File
-append
parameter or use the redirect operator >>. In both cases, the contents of the output will be added to the existing file.# Append with the Out-File cmdlet
'Apple' | Out-File -FilePath C:tempfruits.txt -Append
Get-Content -Path c:tempfruits.txt
# Result
Apple
# Append with the redirect operator
'Pear' >> C:tempfruits.txt
Get-Content -Path c:tempfruits.txt
# Result
Apple
Pear
-NoNewLine
parameter.-NoNewLine
parameter to the first Output as well.# Note that you will need to specify NoNewLine for the first entry as well
'BlueBerry;' | Out-File -FilePath C:tempfruits.txt -NoNewline
# Appending more berries
'StrawBerry;' | Out-File -FilePath C:tempfruits.txt -Append -NoNewline
'BlackBerry;' | Out-File -FilePath C:tempfruits.txt -Append -NoNewline
'RaspBerry;' | Out-File -FilePath C:tempfruits.txt -Append -NoNewline
'CranBerry;' | Out-File -FilePath C:tempfruits.txt -Append -NoNewline
Using PowerShell Add-Content
Another option to add content to a file is to use the Add-Content cmdlet. One of the biggest advantages of the Add-Content cmdlet is that it allows you to append content to multiple files at once.
Just like with the Out-File cmdlet and redirect operator, the Add-Content cmdlet creates a new file if the file doesn’t exist
So to simply add content to a file we can use the following command:
Add-Content -Path c:tempfile.txt -Value "New line to add"
To add the same content to multiple files we have a couple of parameters to help us. We can use wildcards in the path to specify the files that we want to update. Also, we can exclude files names and even use a filter.
The example below will add the current date to all TXT files in the path c:tempfiles, except in the file with readme in the filename:
Add-Content -Path C:tempfiles*.txt -Value (Get-Date) -Exclude "readme*"
All the files, except the readme files, are updated:
Both the include and exclude parameters allow you to specify a string array of files that you want or do not want to update. If we take the example from above, we could also use the filter parameter to select only the files that include the word log: The out-file cmdlet will write only the successful result of your command or script to a file. But sometimes you also want warnings or errors to be outputted as well. To achieve this, we can use the redirect operator. It allows you to specify which stream you want to output to a file. Let’s take the script below as an example: The process “Explorer2” doesn’t exist, so the Get-Process cmdlet will throw an error. If we run the script like this, then the process.txt file will be completely empty. However, if we use the redirect operator we can specify which stream we want to output. As you can see, the error is written to the text file with the redirect operator:Add-Content -Path C:tempfiles* -Value (Get-Date) -Filter "*log*"
Write only Errors, Warnings, or Success to file
Function Get-ProcessCpu {
param(
[Parameter(Mandatory = $true)]$name
)
Get-Process -Name $name | select cpu
}
Get-ProcessCpu -name "explorer2" | Out-File C:tempprocess.txt
# Write all results to the file:
Get-ProcessCpu -name "explorer2" *> C:tempprocess.txt
# Write only the error to the file:
Get-ProcessCpu -name "explorer2" 2> C:tempprocess-error-log.txt
# Write only warnings to a file:
Get-ProcessCpu -name "explorer2" 3> C:tempprocess-error-log.txt
Powershell Write to Log File
The best option to write to a log file is to use the Start-Transcript cmdlet, but we can also write our own log function using the Add-Content cmdlet or the redirect operator.
Using the redirect operator will limit your possibilities, but is a great way if you only want to write the errors of a script to a log file:
Function Get-ProcessCpu { param( [Parameter(Mandatory = $true)]$name ) Get-Process -Name $name | select cpu } # Write only errors to a log file Get-ProcessCpu -name "explorer2" 2>> "C:tempfiles$env:computername-process.log"
But when you are writing messages to a log file you probably want to have a bit more control. With log files it’s important we can see when the event happened and the severity of the event. So what we want to do is add a timestamp and an event level to the log message.
This way we can easily read the log file and identity any errors that have occurred.
# Set log file path $logFile = "C:tempfiles$env:computername-process.log" Function Write-Log { param( [Parameter(Mandatory = $true)][string] $message, [Parameter(Mandatory = $false)] [ValidateSet("INFO","WARN","ERROR")] [string] $level = "INFO" ) # Create timestamp $timestamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss") # Append content to log file Add-Content -Path $logFile -Value "$timestamp [$level] - $message" } Write-Log -level ERROR -message "String failed to be a string"
The function above is an example of a simple log file creator for PowerShell that allows you to write messages (events) to a log file with the severity and timestamp.
Wrapping Up
As you have seen there are multiple ways in PowerShell to output the results to a file. To quickly output something to a file you can use the redirect operator or the Out-File cmdlet.
When you want to export the output to a CSV file, then make sure that you read this article. It’s also possible to replace content inside a file using the Replace method.
If you have any questions, just drop a comment below.
При выполнении компиляции нужно стандартный вывод ошибок направить в файл «error.txt», НО, при этом в терминал тоже должен быть этот же вывод:
g++ test.cpp -o test 2>> error.txt
-
Вопрос заданболее трёх лет назад
-
1113 просмотров
Именно ошибок ? тогда проще всего в файл, а потом его прочитать
а если всего подряд, тогда
g++ test.cpp -o test 2>&1 | Tee-Object -Filepath error.txt
Нашёл ещё вариант
invoke-command { 'txt1'; write-error 'err'; 'txt2' } -ErrorVariable e
#пример вызова внешней команды
invoke-command { python 1.py 2>&1 } -ErrorVariable e
$e | Out-File error.txt
Пригласить эксперта
-
Показать ещё
Загружается…
09 июн. 2023, в 01:21
10000 руб./за проект
09 июн. 2023, в 01:06
50000 руб./за проект
09 июн. 2023, в 00:36
1000 руб./за проект
Минуточку внимания
Как записать в файл лога только ошибки?
Вероятно вы уже встречали не совсем очевидные знаки типа 2>&1
Давайте разберемся что это и как этим пользоваться.
Что бы понимать какие вообще есть потоки, приведу следующую таблицу:
0 | stdin | Стандартный ввод |
1 | stdout | Стандартный вывод |
2 | stderr | Стандартный вывод ошибок |
В Powershell существует больше потоков
Для перенаправления потока
используется комбинация знаков «больше» и амперсанд: >&
Пример:
taskkill -im programm.exe 2>&1
Варианты перенаправления
Перенаправление в файл
Для перенаправления в файл не нужно указывать знак & — он используется только при перенаправлении одного потока в другой
команда 2> файл
Таким образом мы перенаправляем более узкий набор данных(поток ошибок) в более общий(стандартный поток вывода), что бы направить в файл всю имеющуюся информацию, которую в последствии можно использовать для отладки.
Перенаправление потока в другой поток
команда 2>&1
Использование конструкции 1>&2 не предусмотрено, так как не имеет смысла.
Перенаправление с добавлением
Одинарный знак «>» заменяется на двойной и позволяет записывать вывод потока в конец файла
команда 2>> файл
Перенаправление в Null
С помощью перенаправления потока в Null можно убрать из вывода содержимое этого потока.
команда 2>null
Это очень полезно в Powershell, при использовании утилиты psexec, так как даже при успешном выполнении команды возвращается код ошибки 0. Используйте 2>null если нужно подавить эти строки