如何运行PowerShell脚本并输出详细信息?

5w9g7ksd  于 2023-03-19  发布在  Shell
关注(0)|答案(6)|浏览(313)

我想知道是否有一种方法可以运行PowerShell脚本,这样脚本的每一行的命令和输出都会被打印出来。例如,在Bash中,你会写bash -x myscript或在脚本的顶部放置一个set -x。在Batch中,你会省略传统上留在脚本顶部的@echo off。PowerShell有这些结构的等效物吗?

**我尝试过的方法:**运行powershell -? | sls verbose,但一无所获。

1cklez4t

1cklez4t1#

正如@JamesKo所示,如果你问错了问题,你会得到错误的答案:-(。这里有几个人给出了真诚的答案,原因是(a)缺乏Linux曝光率,(b)你使用了术语“冗长”。在下面的内容中,我将带你了解Linux与PowerShell在这个主题上的关系,但如果你很着急,可以跳到最后的答案。

背景

在PowerShell中,verbose有一个非常具体的含义,而PowerShell man page对此甚至相当模糊:
显示有关命令执行的操作的详细信息。此信息类似于跟踪或事务日志中的信息。仅当命令生成详细消息时,此参数才起作用。
这听起来甚至像是您想要的...但是让我们将其与set -x的Linux文档进行比较,根据您对Linux的喜好,set -x可能是这样的(来自man-pages project)...
shell 应在扩展命令后和执行命令前将每个命令的跟踪写入标准错误。
或者这个(来自gnu)...
打印简单命令、for命令、case命令、select命令和命令及其参数的算术的跟踪,或在展开命令之后和执行命令之前打印关联的单词列表。
您的问题的第一行清楚而简洁地同意这些。但是PowerShell中的详细模式是不同的。简而言之,打开详细模式(无论是使用-Verbose命令行开关还是$VerbosePreference变量)只是启用从详细流到控制台的输出。(就像Linux提供两个流,stdout和stderr一样,PowerShell提供多个流:输出流、错误流、警告流、详细流和调试流。使用这些流的方式与Linux相同--例如,您甚至可以使用commands 4>&1将详细流合并到stdout。(您可以在PowerShell One-Liners的Basic Writing Streams部分中阅读有关PowerShell的多个输出流的更多信息:访问、处理和写入数据以及一个很好的快速参考是Complete Guide to PowerShell Punctuation。)

答案

Set-PSDebug命令将给予与bash等效的跟踪。您甚至可以使用-Trace参数调整跟踪细节。首先,在使用Set-PSDebug之前,下面是控件:

PS> Get-PSDepth
0

如果值为1,则在代码执行时获取每行代码,例如:

PS> Set-PSDebug -Trace 1
PS> Get-PSDepth
DEBUG:    1+  >>>> Get-PSDepth
DEBUG:  141+  >>>> {
DEBUG:  142+   >>>> $nest = -1
DEBUG:  143+   >>>> $thisId = $pid
DEBUG:  144+  while ( >>>> (ps -id $thisId).Name -eq 'powershell') {
DEBUG:  145+    >>>> $thisId = (gwmi win32_process -Filter "processid='$thisId'").ParentProcessId
DEBUG:  146+    >>>> $nest++
DEBUG:  144+  while ( >>>> (ps -id $thisId).Name -eq 'powershell') {
DEBUG:  148+   >>>> $nest
0
DEBUG:  149+  >>>> }

如果值为2,您还可以获得变量赋值和代码路径:

PS> Set-PSDebug -Trace 2
PS> Get-PSDepth
DEBUG:    1+  >>>> Get-PSDepth
DEBUG:     ! CALL function '<ScriptBlock>'
DEBUG:  141+  >>>> {
DEBUG:     ! CALL function 'Get-PSDepth'  (defined in file 'C:\Users\msorens\Documents\WindowsPowerShell\profile.ps1')
DEBUG:  142+   >>>> $nest = -1
DEBUG:     ! SET $nest = '-1'.
DEBUG:  143+   >>>> $thisId = $pid
DEBUG:     ! SET $thisId = '9872'.
DEBUG:  144+  while ( >>>> (ps -id $thisId).Name -eq 'powershell') {
DEBUG:  145+    >>>> $thisId = (gwmi win32_process -Filter "processid='$thisId'").ParentProcessId
DEBUG:     ! SET $thisId = '10548'.
DEBUG:  146+    >>>> $nest++
DEBUG:     ! SET $nest = '0'.
DEBUG:  144+  while ( >>>> (ps -id $thisId).Name -eq 'powershell') {
DEBUG:  148+   >>>> $nest
0
DEBUG:  149+  >>>> }

这些是我编写的一个名为Get-PSDepth的简单cmdlet的痕迹,它打印带有DEBUG前缀的命令、赋值等,并与实际输出混合在一起,在本例中是仅包含0的单行。

i86rm4rw

i86rm4rw2#

您可以随时在脚本中使用以下内容。
$详细首选项=“继续”

注意:您必须以提升模式打开shell。

以下截图供参考。

希望有帮助。

5uzkadbs

5uzkadbs3#

要让PowerShell脚本能够从参数/命令行接收参数,即使没有任何参数,也需要添加[CmdletBinding()] param ()
示例脚本:Test-Output.ps1

[CmdletBinding()] param ()
Write-Host "Test output on OS $($Env:OS)"
Write-Verbose "Test VERBOSE output on OS $($Env:OS)"

1.在PowerShell中执行脚本:

PS C:\> .\Test-Output.ps1 -Verbose

1.在Linux上的PowerShell中执行脚本:

/$ pwsh
PS /> ./Test-Output.ps1 -Verbose

1.在Windows上使用PowerShell.exe执行脚本:

C:\> powershell.exe Test-Output.ps1 -Verbose

1.在Windows上使用pwsh.exe PowerShell核心执行脚本:

C:\> pwsh.exe Test-Output.ps1 -Verbose

1.在Linux上使用pwsh PowerShell核心执行脚本:

/$ pwsh Test-Output.ps1 -Verbose

Windows上的输出示例:

Test output on OS Windows_NT
VERBOSE: Test VERBOSE output on OS Windows_NT

Linux上的示例输出:

Test output on OS 
VERBOSE: Test VERBOSE output on OS
zu0ti5jz

zu0ti5jz4#

这其实很简单,每个PowerShell CMDLET都有一个内置的Verbose标记。例如:

Test-Connection -ComputerName www.google.com -Verbose

就这些了。希望能有所帮助

nbnkbykc

nbnkbykc5#

注意:此答案最初是针对Windows Powershell needs to print out information for a particular command regardless of whether it successfully executed or Not中的重复问题发布的。
要补充和详细说明Michael Sorens' helpful answer

在有限制的情况下 ,您可以使用Set-PSDebug-Trace 1让PowerShell在执行脚本语句之前回显这些语句;然而,这更像bashset -o verbose/set -v选项而不是set -o xtrace/set -x,因为回显的命令是 * 未展开的***;详情如下:

# Start tracing statements.
Set-PSDebug -Trace 1

try 
{

  # Sample command
  cmd /c echo 'hi there' $HOME

}
finally {
  Set-PSDebug -Trace 0 # Turn tracing back off.
}

以上结果为:

DEBUG:    4+  >>>> cmd /c echo 'hi there' $HOME
"hi there" C:\Users\jdoe
DEBUG:    6+  >>>> Set-PSDebug -Trace 0 # Turn tracing off.

虽然这种方法几乎不需要额外的工作,但其局限性如下:

  • 你不能控制跟踪语句的前缀。(例如DEBUG: 4+ >>>>,其中4是行号。
  • 将跟踪设置为“off”也总是会生成跟踪语句。
  • 没有办法 * 捕获或抑制 * 跟踪输出-它总是打印到主机(控制台);但是,您可以通过PowerShell CLI从PowerShell * 外部 * 捕获它-请参见this answer
  • 从PowerShell 7.2开始,使用行续行跨越多行的命令只回显其 first 行(参见GitHub issue #8113)。
  • 也许最重要的是,被回显的语句是它们的文本源代码表示,因此可以包含 * 未展开的 * 变量引用和表达式,例如上面示例中的$HOME
  • GitHub issue #9463提出了 expanded 值(即变量和表达式 * 被它们的值 * 替换),例如,在bash中使用set -x会得到这样的结果。
  • 虽然这对于调用 * 外部程序 *(其参数总是 * 字符串 *)是可行的,但挑战在于调用 *PowerShell命令 * 支持任意.NET类型的参数,并非所有这些参数都具有忠实的 * 字符串文字表示 *;也就是说,即使是仅用于人眼的字符串表示也比 * 未展开 * 的值更可取。
    如果需要查看 * 扩展的 * 参数值和/或控制输出格式/目标

注:

  • 尽管**Invoke-Expression ( iex ) should generally be avoided*存在固有的安全风险,而且通常有更好、更安全的选项,但它确实提供了一种解决方案--一如既往, 确保完全控制传递给Invoke-Expression * 的字符串中的内容,以避免可能注入不需要的命令。
  • 该解决方案要求您构造字符串以通过 up-front 扩展(字符串插值)传递给Invoke-Expression,以便在执行时生成的命令行只包含 literal arguments,从而回显命令行可以描绘出调用的可执行文件及其参数的全貌。
  • 如上所述,只有在调用 * 外部程序 *(如msbuild)时,这才是可靠的。

首先,定义一个helper函数,它接受命令行字符串,回显它,然后通过Invoke-Expression执行它:

# !! IMPORTANT:
# !! Only pass *trusted* strings to this function - the
# !! argument is blindly passed to Invoke-Expression.
function Invoke-AfterEchoing {
  param([string] $commandLine)

  # Echo the command line to be executed,
  # using the verbose output stream in this example:
  Write-Verbose -Verbose "Executing: $commandLine"

  Invoke-Expression $commandLine

}

现在可以构造命令行字符串并将其传递给helper函数:

Invoke-AfterEchoing @"
& "$msbuild" .\blabBlah.csproj /t:Clean
"@

Invoke-AfterEchoing @"
& "$msbuild" .\blabBlah.csproj /t:Build /p:Configuration=Dev
"@

注:

  • 可扩展的 here-string@"<newline>...<newline>"@)用于简化字符串内部引用。
  • 选择 expandable 形式是为了确保可执行路径和所有参数都是 * 展开的 *,因此作为它们的 * 文字值 * 嵌入到结果字符串中,这样回显字符串时就会显示所有实际值。
  • 调用操作符&用于调用msbuild,这在语法上是必要的,假定其路径被传递 * 加引号 *,如果$msbuild包含带有空格 * 的路径 *,则这又是必要的。

输出将如下所示:

VERBOSE: Executing: & "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin" .\blabBlah.csproj /t:Clean
# ... (output)

VERBOSE: Executing: & "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin" .\blabBlah.csproj /t:Build /p:Configuration=Dev
# ... (output)
mqxuamgl

mqxuamgl6#

如果您在脚本中使用write-verbose,这将自动发生,
然而,如果你需要手动写函数的详细输出,你需要手动检查每个函数是否被调用了详细标志,这可以通过checking$PSCmdlet.MyInvocation.BoundParameters["Verbose"]在你的函数内部完成。

相关问题