Puppet用のExecPowershellプロバイダーを使用して、いくつかのPowerShellスクリプトを実行しています。スクリプトの実行方法に問題があります。実行方法により、スクリプトが何度も実行されます。プロセスを自分で強制終了する必要がありますが、スクリプト自体は正常に実行されているようです。
簡単な例をまとめて、原因を絞り込むことができました。
再現手順
この問題は、SQLCMD.exeの実行方法、または実行にかかる時間(約1秒)に関連していると確信しています
$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...
Test.ps1の最後にexit;
を追加すると、1回だけ実行されます。
私の最初の質問は、どうすればこれを回避できるかということでした。しかし、exit
を追加することでそれが可能になります。残っている唯一の質問は:なぜこれが起こるのですか?
[〜#〜] edit [〜#〜]:構文エラー/例外(コンマの欠落など)をスクリプトに取り込むとすぐに、スクリプトは無限に実行され、毎回例外がスローされます。したがって、exit
は回避策ですが、例外に対しては機能しないため、依然として危険です。
Powershellは、標準入力として受け取るものに敏感であるようです(<を使用してstdinをリダイレクトします)。予期しない文字を受信している可能性があります。すべての改行を削除し、スクリプトをメモ帳に保存することをお勧めします。したがって、スクリプトは次のようになります。
$instance = ''; $latest_output = "Hi"; $cmd = "etc...
いくつかのテストで、使用するエンコーディング、空白、文字に応じて異なる動作を受け取りました。ちょうどその方法かもしれません cmdリダイレクト 入力。
Githubの powershell puppet project に問題を投稿することもできます。
また、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は、入力リダイレクトに関しては間違いなく奇妙な動作を示します。