Почему PowerShell показывает удивительное поведение во втором примере ниже?
Во-первых, пример нормального поведения:
PS C:\> & cmd /c "echo Hello from standard error 1>&2"; echo "`$LastExitCode=$LastExitCode and `$?=$?"
Hello from standard error
$LastExitCode=0 and $?=True
Никаких неожиданностей. Я печатаю сообщение стандартной ошибки (используя cmd
's echo
). Я проверяю переменные $?
и $LastExitCode
. Они равны True и 0 соответственно, как и ожидалось.
Однако, если я попрошу PowerShell перенаправить стандартную ошибку на стандартный вывод поверх первой команды, я получу ошибку NativeCommandError:
PS C:\> & cmd /c "echo Hello from standard error 1>&2" 2>&1; echo "`$LastExitCode=$LastExitCode and `$?=$?"
cmd.exe : Hello from standard error
At line:1 char:4
+ cmd <<<< /c "echo Hello from standard error 1>&2" 2>&1; echo "`$LastExitCode=$LastExitCode and `$?=$?"
+ CategoryInfo : NotSpecified: (Hello from standard error :String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
$LastExitCode=0 and $?=False
Мой первый вопрос: почему ошибка NativeCommandError?
Во-вторых, почему $?
False, если cmd
выполнен успешно и $LastExitCode
равен 0? Документация PowerShell об автоматических переменныхне определяет явно $?
. Я всегда предполагал, что это True тогда и только тогда, когда $LastExitCode
равно 0, но мой пример противоречит этому.
Вот как я столкнулся с таким поведением в реальном мире (упрощенно). Это действительно ФУБАР. Я вызывал один сценарий PowerShell из другого. Внутренний скрипт:
cmd /c "echo Hello from standard error 1>&2"
if (! $?)
{
echo "Job failed. Sending email.."
exit 1
}
# Do something else
Запустив это просто как .\job.ps1
, он работает нормально, и электронная почта не отправляется. Однако я вызывал его из другого сценария PowerShell, записывая в файл .\job.ps1 2>&1 > log.txt
. В этом случае отправляется электронное письмо! То, что вы делаете вне сценария с потоком ошибок, влияет на внутреннее поведение сценария. Наблюдение за явлением меняет результат. Это похоже на квантовую физику, а не на сценарий!
[Интересно: .\job.ps1 2>&1
может взорваться или не взорваться в зависимости от того, где вы его запустите]