Я использую поставщик Exec Powershell для Puppet для запуска некоторых сценариев PowerShell. У меня проблема с тем, как он выполняет мой скрипт. Метод выполнения заставляет сценарий запускаться снова и снова. Я вынужден сам убить процесс, но сам скрипт вроде работает нормально.
Мне удалось собрать простой пример и сузить причину.
Действия по воспроизведению
Я почти уверен, что проблема связана с тем, как я выполняю 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>
Теперь вместо этого выполните такой сценарий, который выполняется бесконечно. Это проблемный синтаксис, который использует поставщик Exec в Puppet:
C:\Users\Administrator>powershell.exe -Command - < C:\backups\scripts\test.ps1
Updating...
Updating...
Updating...
Updating...
Если я добавлю exit;
до конца test.ps1 он выполняется только один раз.
Мой первоначальный вопрос заключался в следующем: как мне этого избежать? Но добавив exit
делает это для меня. Единственный оставшийся вопрос: Почему это происходит?
РЕДАКТИРОВАТЬ: Как только вы внесете в сценарий синтаксическую ошибку / исключение (например, пропущенную запятую), сценарий будет выполняться бесконечно, каждый раз выбрасывая исключение. Так что пока exit
- обходной путь, он все еще опасен, поскольку не работает с исключениями.
Powershell, похоже, чувствителен к тому, что он получает в качестве стандартного ввода (используя <для перенаправления stdin). Он может получать символы, которых не ожидает. Я бы рекомендовал удалить все символы новой строки и сохранить ваш скрипт в блокноте. Итак, ваш сценарий будет выглядеть примерно так:
$instance = ''; $latest_output = "Hi"; $cmd = "etc...
Проведя несколько тестов, я получил разное поведение в зависимости от используемой кодировки, пробелов и символов. Может быть просто путь cmd перенаправляет ввод.
Вы также можете опубликовать свою проблему в кукольный проект PowerShell в гитхабе.
Кроме того, вы, возможно, не захотите использовать 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 определенно демонстрирует странное поведение, когда дело доходит до перенаправления ввода.