Powershell 脚本以某种方式执行时会陷入无限循环

Powershell 脚本以某种方式执行时会陷入无限循环

我正在使用 Puppet 的 Exec Powershell 提供程序来运行一些 powershell 脚本。我对它执行脚本的方式感到困惑。执行方法导致脚本反复运行。我不得不自己终止该进程,但脚本本身似乎运行正常。

我已经能够整理一个简单的例子,并缩小原因范围。

重现步骤

  1. 创造C:\备份\脚本\测试.ps1内容如下:

我很确定该问题与我执行 SQLCMD.exe 的方式有关,或者与执行所需的时间有关(大约一秒钟)

    $instance = '';
    $latest_output = "Hi";

    $cmd = "sqlcmd.exe -E -S .$instance -h -1 -m 1 -Q `"SET NOCOUNT ON; USE [master]; SELECT @@VERSION;`"";

    $output = [string](cmd.exe /C "$cmd");
    $output = $output.Trim(' ');

    if ($output -eq $latest_output)
    {
        Write-Host "Up to date.";
    }
    else
    {
        Write-Host "Updating...";
    }
  1. 打开CMD.exe,运行以下命令,效果如预期:

    C:\Users\Administrator>powershell.exe -Command C:\backups\scripts\test.ps1
    Updating...
    
    C:\Users\Administrator>
    
  2. 现在改为像这样执行脚本,它将无限执行。这是 Puppet 中的 Exec 提供程序使用的有问题的语法:

    C:\Users\Administrator>powershell.exe -Command - < C:\backups\scripts\test.ps1
    Updating...
    Updating...
    Updating...
    Updating...
    
  3. 如果我添加exit;到 test.ps1 的末尾,它只会执行一次。

我最初的问题是,我该如何避免这种情况?但是添加exit对我来说确实如此。剩下的唯一问题是:为什么会发生这种情况?

编辑:只要您在脚本中引入语法错误/异常(例如缺少逗号),脚本就会无限执行,每次都会抛出异常。因此,虽然这exit是一种解决方法,但它仍然很危险,因为它无法应对异常。

环境

  • Windows 2008 R2 服务器标准版
  • 具有高级服务的 Microsoft SQL Server Express 10.50.2500
  • Powershell 2.0

答案1

Powershell 似乎对它接收的标准输入很敏感(使用 < 重定向 stdin)。它可能会收到它不期望的字符。我建议删除所有换行符并将脚本保存在记事本中。因此您的脚本看起来会像这样:

$instance = ''; $latest_output = "Hi"; $cmd = "etc...

我做了几个测试,根据使用的编码、空格和字符,我得到了不同的行为。可能只是cmd 重定向输入。

您也可以将问题发布到powershell puppet 项目在 github 上。

此外,您可能不想使用 write-host,因为它是控制台的标准输出,并且也可能存在问题。

在一个稍微不相关的注释中尝试这个:

$psi = New-Object System.Diagnostics.ProcessStartInfo;
$psi.FileName = "powershell.exe"
$psi.UseShellExecute = $false
$psi.RedirectStandardInput = $true
$p = [System.Diagnostics.Process]::Start($psi)

按 ctrl-c 你就会看到类似这样的内容:

PS C:\> PS C:\>

当涉及输入重定向时,Powershell 肯定会表现出奇怪的行为。

相关内容