Azure PowerShell 输出未在控制台中显示。

5

我在Azure PowerShell中创建了一个脚本。

如果我使用"echo"命令,它会将输出显示到控制台上。

但是,如果我使用Write-Output和Write-Error,则看不到输出。

我已将脚本“change-to-static.ps1”上传到存储帐户。然后我使用顶部栏上的按钮打开“Cloud Shell”。然后在PowerShell控制台中键入“./change-ip-to-static.ps1”。

因此,除非我将“Write-Output”和“Write-Error”替换为“echo”或“print”,否则该脚本不会产生任何输出。

请帮帮我。我该怎么做才能看到输出?

以下是脚本内容。

类似问题请参见如何在PowerShell中输出内容。我已经阅读过了,但是没有具体的示例说明如何实现我的目标,即如何修改我的脚本以查看输出。并且在我的情况下,即使我重定向到文本文件,它也不会输出。但是,在我的情况下,“echo”和“print”等命令可以工作,但它们在上面的示例中没有涉及。请参见以下脚本。

$IPs = Get-AzPublicIpAddress; 
$Static = "Static";
foreach ($PublicIP in $IPs) {
    $Method = $PublicIP.PublicIpAllocationMethod;
    $Name = $PublicIP.Name;
    if ($Method -eq $Static) {
        $message = "The method of " + $Name + " is already " + $Static;
        Write-Progress -Activity $message;
    }
    else {
        Write-Progress -Activity "Changing the method of "+$Name+" from "+$Method+" to "+$Static+"...";
        $PublicIP.PublicIpAllocationMethod = $Static;
        Set-AzPublicIpAddress -PublicIpAddress $PublicIP;
        Write-Progress -Activity "Querying the method of "+$Name+"...";
        $ModifiedAddress = Get-AzPublicIpAddress -Name $Name -ResourceGroupName $PublicIP.ResourceGroupName -Location $PublicIP.Location
        $NewMethod = $ModifiedAddress.PublicIpAllocationMethod;
        if ($NewMethod -eq $Static) {
            Write-Output "The method for "+$Name+" has successfully changed to "+$Static;
        }
        else {
            Write-Error -Message "Cannot change the method for "+$Name+" to "+$Static+", it is still "+$NewMethod+"!!!";
        }
    }
}

附注:我已根据建议更新了脚本(使用此网址),但仍没有输出。只有“echo”或“print”会输出结果。

另外,Write-Progress 在执行需要几秒钟才能完成的 Set-AzPublicIpAddress 或添加 Start-Sleep 命令时甚至不显示临时消息。它仅在执行 Get-AzPublicIpAddress 时设置。


2
我不确定这是否与您的问题有关,但是您的“if ($Method = Static)”测试应该是“if ($Method -eq $Static)”。我在我的Cloud Shell中使用3个语句(Write-Output、Write-Error和Write-Host)进行了简单的测试,并为每个语句显示了文本。 - Mike
2
当使用Write-Output和Write-Error语句时,不应该使用"+"来连接字符串。应该更像是Write-Output "The method for $Name has successfully changed to $Static"和Write-Error -Message "Cannot change the method for $Name to $Static it is still $NewMethod !!!"。这可能会导致您的问题。 - Mike
2
我拿了你在GitHub上发布的代码,在Azure Cloud Shell中执行了脚本,并能够看到Write-Output语句。如果你没有看到输出,我的唯一猜测是Write-Progess行可能会写在输出的顶部,或者来自Set-AzPublicIpAddress的输出可能会引起问题。你可以尝试几件事情:1)注释掉Write-Progress(进行故障排除)2)使用$result = Set-AzPublicIpAddress -PublicIpAddress $PublicIP来防止输出干扰。 - Mike
1
使用 Write-Verbose - Juanma Feliu
1
同一脚本可以在PowerShell中执行,Write-Output语句可以正常工作。您可以尝试在if ($Method -eq $Static)方法中的Write-Progress之后添加Write-Output cmd,并检查它是否可以工作。 - Delliganesh Sevanesan
显示剩余2条评论
2个回答

4
在阅读您对我的答案的最后一次编辑后,我认为您在使用Write-*命令和脚本逻辑方面存在一些混淆,因此我提供了一个更详细的带有上下文的答案。
在Powershell Azure Cloud Shell中,echoWrite-Output的别名,执行没有参数的echo将清楚地显示这一点(文档在此处)。
PS /home/mikelangelo> echo

cmdlet Write-Output at command pipeline position 1
Supply values for the following parameters:
InputObject:

此外:Unix中的echo命令也可以在Powershell Azure云Shell中运行。
PS /home/mikelangelo> which echo
/usr/bin/echo 
PS /home/mikelangelo> /usr/bin/echo ciao mondo
ciao mondo

print 不是 Powershell 的别名,因此当使用 print 关键字时,Unix 对应的命令将始终被执行(目前是一个指向run-mailcap的符号链接,但我不清楚它在你的使用情况下如何发挥作用)。

PS /home/mikelangelo> which print
/usr/bin/print

基本上,echoWrite-Output 都可以使用,因为它们调用同一个命令,但是如果直接执行 /usr/bin/echo,会混合技术并且影响可移植性。
回到问题: Write-Output 的工作正常。逻辑有误:您使用 = 作为比较运算符,但您需要使用 -eqWrite-Progress 需要以不同的方式使用,将其替换为 Write-HostWrite-Output。请参考文档以获取解释。
请注意,Write-Output 将对象发送到管道下游,最终可以表示为控制台输出。 另一方面,Write-ProgressWrite-Host 不会生成输出-后者会将对象发送到主机以供显示,因此建议使用 Write-Host 显示控制台中的内容。请参考此问题获取有关 Write-HostWrite-Output 和 Powershell 管道的更多详细信息。

问题不在于“write-progress”,而在于“Write-Output”和“Write-Error”。在发布问题之前,我已经阅读了您提到的链接。“write-progress”只会给出间歇性结果(仅在进度中),而“Write-Output”和“Write-Error”应该提供永久输出。如果您阅读我的问题,它并没有提到关于“Write-Progress”的问题,它只提到了关于“Write-Output”和“Write-Error”的问题。 - Maxim Masiutin
1
我的回答在这里(我已经更新了它以便更清楚)。write-output-error被正确使用,只是因为比较运算符不正确而从未执行。 - Mike L'Angelo
1
不完全是。我明白现在你在控制台上看到了想要看到的内容,但是有一种更好的方式来产生控制台输出和显示进度信息。我扩展了我的答案,提供了更多的背景和参考资料。 - Mike L'Angelo
1
错误的比较总是导致 '$true',所以 if 总是被验证。write-progress 产生的输出是瞬时的,因此它在 write-progress 结束时就消失了。尝试执行命令行示例中发布的代码,并删除 start-sleep -m 150,或将其替换为 -m 1。重点是,write-progress 不会在控制台中显示输出,只会在 命令运行期间 显示进度条和注释。您可以使用它来获得命令未提供的结果,因此使用方式在概念上是错误的。 - Mike L'Angelo
1
踩可以是关于问题的_质量_,而不仅仅是它是否符合SO政策。您可以改进它并保留它以保存像我和Manuel Batsching这样的人所做的工作。顺便说一下,踩可以被取消。 - Mike L'Angelo
显示剩余4条评论

2

和其他评论者一样,我可以确认你的代码在Azure Cloud Shell中可以正常工作。

我注意到只有在至少有一个动态公共IP地址可以被脚本更改为静态时才会有输出。原因是,在这种情况下,你使用Write-Output将字符串返回到控制台。

如果没有剩余的动态公共IP地址,你的脚本只会写入进度消息,但是由于脚本执行结束得太快,你永远看不到它,因为进度消息不会停留。

Write-Progress行下面放置命令Start-Sleep -Seconds 2,你就会明白我的意思:

$IPs = Get-AzPublicIpAddress;
$Static = "Static";
foreach ($PublicIP in $IPs) {
    $Method = $PublicIP.PublicIpAllocationMethod;
    $Name = $PublicIP.Name;
    if ($Method -eq $Static) {
        $message = "The method of $Name is already $Static";
        Write-Progress -Activity $message;
        Start-Sleep -Seconds 2 # This will keep the script running 2 seconds longer and the message visible.
    }
    else {
        Write-Progress -Activity "Changing the method of $Name from $Method to $Static ...";
        $PublicIP.PublicIpAllocationMethod = $Static;
        Set-AzPublicIpAddress -PublicIpAddress $PublicIP;
        Write-Progress -Activity "Querying the method of $Name ...";
        $ModifiedAddress = Get-AzPublicIpAddress -Name $Name -ResourceGroupName $PublicIP.ResourceGroupName
        $NewMethod = $ModifiedAddress.PublicIpAllocationMethod;
        if ($NewMethod -eq $Static) {
            Write-Output "The method for $Name has successfully changed to $Static";
        }
        else {
            Write-Error -Message "Cannot change the method for $Name to $Static, it is still $NewMethod!!!";
        }
    }
}

Write-Progress 可能不是你想用来输出脚本进度的 cmdlet(尽管它的名字是这样的)。既然我看不出你需要进一步处理脚本的输出,那么你可以用 Write-Host 代替它。


Manuel,我觉得你的回答与我9天前发布的回答没有什么新内容,只是一种错误使用Write-Progress输出的解决方法。结论是相同的:需要以不同的方式使用Write-Progress,可以用Write-Host-Output替换它。 - Mike L'Angelo
WriteOutput 正常工作。只是 Write-Progress 应该被正确使用。在我的情况下,即使进行睡眠,它也不打印任何内容。但它确实在 Set-AzPublicIpAddress 和 Get-AzPublicIpAddress 过程中的状态行中产生了临时状态。因此,我只需要将“if”块中的第一个“Write-Progress”替换为 WriteOutput。无论如何,你的解释是脚本返回得太快,所以我没有看到 WriteProgress 的任何内容,这基本上是正确的,谢谢!我已经修改了 github 上的脚本,现在它能像我想要的那样工作了。 - Maxim Masiutin
在我的情况下,WriteProgress 仅在 Get-AzPublicIpAddress 过程中显示任何内容。无论 Set-AzPublicIpAddress 或 Start-Sleep 过程需要多长时间,或者我是否添加了 "| Out-null",它都不会在这些过程中显示任何内容。无论如何,WriteProgress 并不是那么重要,因为它只产生临时输出。 - Maxim Masiutin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接