echo $如何?工作?
How does echo $? work?
我正在编写一些 PowerShell 脚本来进行一些构建自动化。我发现 here echo $? returns true 或 false 取决于前面的陈述。我刚刚发现 echo 是 Write-Output 的别名。 Write-Host $? 也可以。但是我仍然不清楚 $? 是如何工作的。有人可以就此说几句话吗?搜索回声 $?网上没给我太多。
您找到了完整的标点符号表 here。答案(取自图表):
Execution status of the last operation ($true or $false); contrast
with $LastExitCode that reports the exit code of the last
Windows-based program executed.
用更详细的信息补充 :
tl;dr
自动变量$?
(见Get-Help about_Automatic Variables
)包含一个布尔值反映在最近的语句[=172]中是否发生任何非终止错误 =].
- 由于
$?
设置在 每个 语句之后,您必须在感兴趣的语句之后立即检查它,或者保存它以供以后检查。
- 请参阅下文了解可能违反直觉的行为。
自动变量$LASTEXITCODE
通过记录[=97来补充 =]最近执行的外部命令行实用程序(例如findstr
)的特定退出代码。
$LASTEXITCODE
补充 $?
,因为 $?
仅反映 抽象 外部实用程序的成功或失败 - 退出代码 0
映射到 $True
,任何非零退出代码映射到 $False
- 而 $LASTEXITCODE
包含实际退出代码。
- 由于
$LASTEXITCODE
仅为外部命令行实用程序设置,因此其值通常比 $?
更有效,后者在 every 语句之后设置.
关于 $?
的设置方式,以及它的值准确表示的内容,有很多 细节:
$?
仅反映 非终止 错误 的发生,因为(更罕见)terminating 错误默认终止当前命令行/脚本的执行,要处理它们,您需要使用 try / catch
(首选)或 trap
(参见 Get-Help about_Try_Catch_Finally
and Get-Help about_Trap
).
- 相反,您可以选择将非终止错误视为终止错误,使用首选项变量
$ErrorActionPreference
或通用 cmdlet 参数
-ErrorAction
(别名 -EA
)- 参见 Get-Help about_Preference_Variables
and Get-Help about_CommonParameters
。
除非明确忽略(使用常见的 -ErrorAction Ignore
cmdlet 参数),所有非终止错误(并捕获终止errors) 收集在自动 $Error
集合 中,按时间倒序排列;也就是说,元素 $Error[0]
包含最新的错误。
对于多个输入对象被传递到的命令,包含$False
的$?
只告诉你至少一个 输入对象的处理失败。换句话说:输入对象的任何子集都可能发生错误,包括所有。
- 要确定确切的错误计数和有问题的输入对象,您必须检查
$Error
集合。
使用非远程间接执行 cmdlets,您向其传递目标命令以执行 - 例如Invoke-Expression
、Start-Process
和 Start-Job
和 Invoke-Command
没有 -ComputerName
参数(不涉及远程处理 - 请参阅below) - $?
原则上只反映目标命令是否可以被调用,不管该命令随后是否报告错误。
- 一个简单的例子:
Invoke-Expression '1 / 0'
将 $?
设置为 $True
(!),因为 Invoke-Expression
能够解析并 调用 表达式,即使表达式本身失败了。
- 同样,检查
$Error
集合会告诉您目标命令是否报告了错误以及报告了哪些错误。
使用 远程处理(总是间接执行)cmdlet,特别是 Invoke-Command
和 -ComputerName
参数(这是典型的),而且还带有隐式远程处理 cmdlet,$?
确实 反映了 目标命令 是否报告任何错误。
一个简单的例子(必须是来自 提升的 控制台的 运行 并且假定本地计算机已经设置为远程处理):
Invoke-Command -ComputerName . { 1 / 0 }
,因为涉及remoting,确实将$?
设置为$False
以反映目标命令1 / 0
.[=152的失败=]
请注意,即使本地计算机 (.
) 是目标,使用 -ComputerName
也总是使用远程处理。
请注意,根据设计,远程报告通常 终止 远程发生的错误 非终止 错误,据推测,一台目标机器上的正常终止错误不会中止所有其他机器上的处理。
反映 $?
中错误的命令示例:
# Invoking a non-existing cmdlet or utility directly.
NoSuchCmd
# Ditto, via call operator &.
# Note, however, that using a *script block* with & behaves differently - see below.
& 'NoSuchCmd'
# Invoking a cmdlet with invalid parameter syntax.
Get-ChildItem -NoSuchParameter
# Invoking a cmdlet with parameter values that cause a (non-terminating) runtime error.
Get-ChildItem NoSuchFile
# Invoking an external utility that reports a nonzero exit code.
findstr -nosuchoptions
# The specific exit code is recorded in $LASTEXITCODE,
# until the next external utility is called.
# Runtime exceptions
1 / 0
# A cmdlet that uses remoting:
# (Must be run from an elevated session, and the local machine must
# be configured for remoting first - run `winrm quickconfig`).
# Note that remoting would NOT be involved WITHOUT the -ComputerName parameter,
# in which case `$?` would only reflect whether the script block could be
# _invoked_, irrespective of whether its command(s) then fail or not.
Invoke-Command -ComputerName . { 1 / 0 }
# A .NET method that throws an exception.
# Note: Outside of a `try/catch` handler, this is a non-terminating error.
# Inside a `try/catch` handler, .NET exceptions are treated as terminating
# and trigger the `catch` block.
[System.IO.Path]::IsPathRooted('>')
不反映 $?
中错误的命令示例:
<#
Non-remoting indirect execution cmdlets:
$? reflects only whether the specified command could be
*invoked*, irrespective of whether the command itself then failed or not.
In other words: $? is only $False if the specified command could not even be
executed, such as due to invalid parameter syntax, an ill-formed target
command, or a missing target executable.
#>
# Invoking a command stored in a script block.
& { 1 / 0 }
# Invoking an expression stored in a string.
Invoke-Expression '1 / 0'
# Starting a background job.
Start-Job { 1/ 0 }
# The *non-remoting* form of Invoke-Command (WITHOUT -ComputerName).
Invoke-Command { 1 / 0 }
我正在编写一些 PowerShell 脚本来进行一些构建自动化。我发现 here echo $? returns true 或 false 取决于前面的陈述。我刚刚发现 echo 是 Write-Output 的别名。 Write-Host $? 也可以。但是我仍然不清楚 $? 是如何工作的。有人可以就此说几句话吗?搜索回声 $?网上没给我太多。
您找到了完整的标点符号表 here。答案(取自图表):
Execution status of the last operation ($true or $false); contrast with $LastExitCode that reports the exit code of the last Windows-based program executed.
用更详细的信息补充
tl;dr
自动变量
$?
(见Get-Help about_Automatic Variables
)包含一个布尔值反映在最近的语句[=172]中是否发生任何非终止错误 =].- 由于
$?
设置在 每个 语句之后,您必须在感兴趣的语句之后立即检查它,或者保存它以供以后检查。 - 请参阅下文了解可能违反直觉的行为。
- 由于
自动变量
$LASTEXITCODE
通过记录[=97来补充 =]最近执行的外部命令行实用程序(例如findstr
)的特定退出代码。$LASTEXITCODE
补充$?
,因为$?
仅反映 抽象 外部实用程序的成功或失败 - 退出代码0
映射到$True
,任何非零退出代码映射到$False
- 而$LASTEXITCODE
包含实际退出代码。- 由于
$LASTEXITCODE
仅为外部命令行实用程序设置,因此其值通常比$?
更有效,后者在 every 语句之后设置.
关于 $?
的设置方式,以及它的值准确表示的内容,有很多 细节:
$?
仅反映 非终止 错误 的发生,因为(更罕见)terminating 错误默认终止当前命令行/脚本的执行,要处理它们,您需要使用try / catch
(首选)或trap
(参见Get-Help about_Try_Catch_Finally
andGet-Help about_Trap
).- 相反,您可以选择将非终止错误视为终止错误,使用首选项变量
$ErrorActionPreference
或通用 cmdlet 参数
-ErrorAction
(别名-EA
)- 参见Get-Help about_Preference_Variables
andGet-Help about_CommonParameters
。
- 相反,您可以选择将非终止错误视为终止错误,使用首选项变量
除非明确忽略(使用常见的
-ErrorAction Ignore
cmdlet 参数),所有非终止错误(并捕获终止errors) 收集在自动$Error
集合 中,按时间倒序排列;也就是说,元素$Error[0]
包含最新的错误。对于多个输入对象被传递到的命令,包含
$False
的$?
只告诉你至少一个 输入对象的处理失败。换句话说:输入对象的任何子集都可能发生错误,包括所有。- 要确定确切的错误计数和有问题的输入对象,您必须检查
$Error
集合。
- 要确定确切的错误计数和有问题的输入对象,您必须检查
使用非远程间接执行 cmdlets,您向其传递目标命令以执行 - 例如
Invoke-Expression
、Start-Process
和Start-Job
和Invoke-Command
没有-ComputerName
参数(不涉及远程处理 - 请参阅below) -$?
原则上只反映目标命令是否可以被调用,不管该命令随后是否报告错误。- 一个简单的例子:
Invoke-Expression '1 / 0'
将$?
设置为$True
(!),因为Invoke-Expression
能够解析并 调用 表达式,即使表达式本身失败了。 - 同样,检查
$Error
集合会告诉您目标命令是否报告了错误以及报告了哪些错误。
- 一个简单的例子:
使用 远程处理(总是间接执行)cmdlet,特别是
Invoke-Command
和-ComputerName
参数(这是典型的),而且还带有隐式远程处理 cmdlet,$?
确实 反映了 目标命令 是否报告任何错误。一个简单的例子(必须是来自 提升的 控制台的 运行 并且假定本地计算机已经设置为远程处理):
Invoke-Command -ComputerName . { 1 / 0 }
,因为涉及remoting,确实将$?
设置为$False
以反映目标命令1 / 0
.[=152的失败=] 请注意,即使本地计算机 (.
) 是目标,使用-ComputerName
也总是使用远程处理。请注意,根据设计,远程报告通常 终止 远程发生的错误 非终止 错误,据推测,一台目标机器上的正常终止错误不会中止所有其他机器上的处理。
反映
$?
中错误的命令示例:# Invoking a non-existing cmdlet or utility directly. NoSuchCmd # Ditto, via call operator &. # Note, however, that using a *script block* with & behaves differently - see below. & 'NoSuchCmd' # Invoking a cmdlet with invalid parameter syntax. Get-ChildItem -NoSuchParameter # Invoking a cmdlet with parameter values that cause a (non-terminating) runtime error. Get-ChildItem NoSuchFile # Invoking an external utility that reports a nonzero exit code. findstr -nosuchoptions # The specific exit code is recorded in $LASTEXITCODE, # until the next external utility is called. # Runtime exceptions 1 / 0 # A cmdlet that uses remoting: # (Must be run from an elevated session, and the local machine must # be configured for remoting first - run `winrm quickconfig`). # Note that remoting would NOT be involved WITHOUT the -ComputerName parameter, # in which case `$?` would only reflect whether the script block could be # _invoked_, irrespective of whether its command(s) then fail or not. Invoke-Command -ComputerName . { 1 / 0 } # A .NET method that throws an exception. # Note: Outside of a `try/catch` handler, this is a non-terminating error. # Inside a `try/catch` handler, .NET exceptions are treated as terminating # and trigger the `catch` block. [System.IO.Path]::IsPathRooted('>')
不反映
$?
中错误的命令示例:<# Non-remoting indirect execution cmdlets: $? reflects only whether the specified command could be *invoked*, irrespective of whether the command itself then failed or not. In other words: $? is only $False if the specified command could not even be executed, such as due to invalid parameter syntax, an ill-formed target command, or a missing target executable. #> # Invoking a command stored in a script block. & { 1 / 0 } # Invoking an expression stored in a string. Invoke-Expression '1 / 0' # Starting a background job. Start-Job { 1/ 0 } # The *non-remoting* form of Invoke-Command (WITHOUT -ComputerName). Invoke-Command { 1 / 0 }