Powershell: Как правильно выводить полные сообщения об ошибках из нового элемента?

#powershell #verbose #new-item

Вопрос:

Я запускаю vagrant команду winrm и замечаю, что команда, которая завершается неудачно, не выводит весь вывод ошибок… Я подумал | , что это может быть использовано для расширения вывода таких команд… но после некоторого поиска в Интернете и пробования нескольких вариантов, таких как:

  • | fl
  • | Format-Table -Wrap -Au

Я все еще получаю a ... в окончательном выводе моего сообщения об ошибке, т. Е. в той части, где команда повторяется.

 NewItemIOError
At line:1 char:1
  New-Item -path C:varlibkubeletetckubernetespki -type SymbolicL ...
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

Описанный выше сбой происходит по ясной и очевидной причине, поэтому мне не нужна помощь в отладке проблемы, скорее мне просто интересно, какой правильный вариант использовать, New-Item чтобы убедиться, что powershell показывает мне все результаты своего неудачного выполнения в автоматизированных средах с 10000s строк журналов.

Каков самый простой способ вывода подробных сообщений об ошибках из нового элемента и аналогичных команд powershell?

Комментарии:

1. Разве это не ... просто для вывода на консоль? (То есть, не содержат ли объекты ошибок всего сообщения?)

2. @Bill_Stewart это делает, как я описал ниже 🙂

3. Правильный. Полезно помнить, что в PowerShell отображение объекта x не обязательно эквивалентно содержимому объекта x . (Другой способ сказать это состоит в том, что отображаемый вывод объекта является форматированным представлением этого объекта.)

Ответ №1:

Проще говоря, точки в сообщении об исключении в консоли предназначены только для отображения — чтобы не создавать стену текста. Если вы хотите отобразить ПОЛНОЕ исключение, вы можете использовать что-то вроде этого:

 try {
    New-Item NONEXISTING:asd.txt -ErrorAction Stop #This will throw error
    Write-Host "If it shows error was not caught"
}
catch {
    $_.Exception | Format-List -Force
}
 

Это отображает информацию, как показано ниже, и дает вам полную информацию об объекте исключения 🙂

 ErrorRecord                 : Cannot find drive. A drive with the name 'NONEXISTING' does not exist.
ItemName                    : NONEXISTING
SessionStateCategory        : Drive
WasThrownFromThrowStatement : False
Message                     : Cannot find drive. A drive with the name 'NONEXISTING' does not exist.
Data                        : {}
InnerException              :
TargetSite                  : System.Management.Automation.PSDriveInfo GetDrive(System.String, Boolean)
StackTrace                  :    at System.Management.Automation.SessionStateInternal.GetDrive(String name, Boolean automount)
                                 at System.Management.Automation.SessionStateInternal.GetDrive(String name, Boolean automount)
                                 at System.Management.Automation.LocationGlobber.GetDriveRootRelativePathFromPSPath(String path, CmdletProviderContext context, Boolean escapeCurrentLocation, PSDriveInfoamp; workingDriveForPath, CmdletProvideramp; providerInstance)
                                 at System.Management.Automation.LocationGlobber.GetProviderPath(String path, CmdletProviderContext context, Boolean isTrusted, ProviderInfoamp; provider, PSDriveInfoamp; drive)
                                 at System.Management.Automation.SessionStateInternal.NewItem(String[] paths, String name, String type, Object content, CmdletProviderContext context)
                                 at Microsoft.PowerShell.Commands.NewItemCommand.ProcessRecord()
HelpLink                    :
Source                      : System.Management.Automation
HResult                     : -2146233087
 

Для полной трассировки сообщений или стека просто выберите $_.Exception.Message или $_.Exception.StackTrace :

 try {
    New-Item NONEXISTING:asd.txt -ErrorAction Stop; #This will throw error
    Write-Host "If it shows error was not caught"
}
catch {
    Write-Host "MESSAGE`n$($_.Exception.Message)"
    Write-Host "STACK TRACE`n$($_.Exception.StackTrace)"
}
 

и это дает информацию:

 MESSAGE
Cannot find drive. A drive with the name 'NONEXISTING' does not exist.
STACK TRACE
   at System.Management.Automation.SessionStateInternal.GetDrive(String name, Boolean automount)
   at System.Management.Automation.SessionStateInternal.GetDrive(String name, Boolean automount)
   at System.Management.Automation.LocationGlobber.GetDriveRootRelativePathFromPSPath(String path, CmdletProviderContext context, Boolean escapeCurrentLocation, PSDriveInfoamp; workingDriveForPath, CmdletProvideramp; providerInstance)
   at System.Management.Automation.LocationGlobber.GetProviderPath(String path, CmdletProviderContext context, Boolean isTrusted, ProviderInfoamp; provider, PSDriveInfoamp; drive)
   at System.Management.Automation.SessionStateInternal.NewItem(String[] paths, String name, String type, Object content, CmdletProviderContext context)
   at Microsoft.PowerShell.Commands.NewItemCommand.ProcessRecord()
 

пс. Если вы хотите получить еще больше информации:

 try {
    New-Item NONEXISTING:asd.txt -ErrorAction Stop
    Write-Host "If it shows error was not caught"
}
catch {
    $_ | Format-List -Force
}
 

Это отобразит всю информацию, включая трассировку сценария (в какой строке произошло исключение).:

 Exception             : System.Management.Automation.DriveNotFoundException: Cannot find drive. A drive with the name 'NONEXISTING' does not exist.
                           at System.Management.Automation.SessionStateInternal.GetDrive(String name, Boolean automount)
                           at System.Management.Automation.SessionStateInternal.GetDrive(String name, Boolean automount)
                           at System.Management.Automation.LocationGlobber.GetDriveRootRelativePathFromPSPath(String path, CmdletProviderContext context, Boolean escapeCurrentLocation, PSDriveInfoamp; workingDriveForPath, CmdletProvideramp; providerInstance)
                           at System.Management.Automation.LocationGlobber.GetProviderPath(String path, CmdletProviderContext context, Boolean isTrusted, ProviderInfoamp; provider, PSDriveInfoamp; drive)
                           at System.Management.Automation.SessionStateInternal.NewItem(String[] paths, String name, String type, Object content, CmdletProviderContext context)
                           at Microsoft.PowerShell.Commands.NewItemCommand.ProcessRecord()
TargetObject          : NONEXISTING
CategoryInfo          : ObjectNotFound: (NONEXISTING:String) [New-Item], DriveNotFoundException
FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.NewItemCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 2
PipelineIterationInfo : {}
PSMessageDetails      :
 

Комментарии:

1. Я бы предложил использовать $Error[0] вместо $_ .

2.@AbrahamZinala в catch блоке $_ предназначен для размещения оскорбительной ошибки; вам нужен только более подробный эквивалент за $Error[0] пределами такого блока, чтобы ссылаться на самую последнюю ошибку.

3. @AbrahamZinala 🙂 Внутри catch блока $_ и $Error[0] эквивалентны, поэтому, хотя вы также можете использовать последнее, оно более подробное и менее очевидное. Если я рекомендовал использовать $Error[0] в catch блоке в своем ответе, скажите мне — он должен быть пересмотрен.

4. Это был комментарий, лол не может вспомнить, какой именно, но они опубликовали ответ, используя $_ его в качестве ошибки. Буду иметь это в виду сейчас. Спасибо!(:

5. Хороший ответ. Я обычно использую | Select-Object * вместо | Format-List -Force