我正在使用 Puppet 的 Exec Powershell 提供程序来运行一些 powershell 脚本。我对它执行脚本的方式感到困惑。执行方法导致脚本反复运行。我不得不自己终止该进程,但脚本本身似乎运行正常。
我已经能够整理一个简单的例子,并缩小原因范围。
重现步骤
- 创造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...";
}
打开CMD.exe,运行以下命令,效果如预期:
C:\Users\Administrator>powershell.exe -Command C:\backups\scripts\test.ps1 Updating... C:\Users\Administrator>
现在改为像这样执行脚本,它将无限执行。这是 Puppet 中的 Exec 提供程序使用的有问题的语法:
C:\Users\Administrator>powershell.exe -Command - < C:\backups\scripts\test.ps1 Updating... Updating... Updating... Updating...
如果我添加
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 肯定会表现出奇怪的行为。