UserData по умолчанию будет работать с Powershell V5.1 в AMI Windows Server 2022 на экземпляре AWS EC2, который раскручивается. Однако я хочу использовать некоторые командлеты, которые поддерживаются только в Powershell версии 7 и выше.
Как мне лучше всего запустить скрипт с Powershell 7+ при загрузке экземпляра с UserData?
В настоящее время у меня есть скрипт, который устанавливает powershell 7, но с этого момента я не уверен, как использовать v7 для запуска остальных команд, которые у меня есть.
Invoke-WebRequest -Uri https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/PowerShell-7.3.1-win-x64.msi -OutFile PowerShell.msi
Start-Process msiexec.exe -ArgumentList '/i PowerShell.msi /quiet' -Wait
Я использую WINDOWS_SERVER_2022_ENGLISH_FULL_BASE AMI.
Я пытался использовать что-то вроде Invoke-Expression
, а также пытался заставить скрипт вызывать себя рекурсивно с некоторыми условными выражениями, например.
# First Run with ps 5.1
if ($PSVersionTable.PSVersion -lt [Version]"7.0") {
Invoke-WebRequest -Uri https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/PowerShell-7.3.1-win-x64.msi -OutFile PowerShell.msi
Start-Process msiexec.exe -ArgumentList '/i PowerShell.msi /quiet' -Wait
cd "C:\Program Files\PowerShell\7"
# Run this same script with ps7
./pwsh $PSCommandPath
exit
}
#
if ($PSVersionTable.PSVersion -gt [Version]"7.0") {
# Do the things I need to do with ps7...
}
Обе мои попытки потерпели неудачу, и с пользовательскими данными ec2 очень сложно получить информацию о том, почему.
Не могли бы вы привести краткий пример блока сценария и оператора вызова? Я не думаю, что смогу войти в pwsh в интерактивном режиме, так как все это нужно делать через скрипт, и никакого вмешательства человека не будет.
Конечно. Вот так: $scriptblock = {Param($text)Write-Host -Object "$text " -NoNewline;};& $scriptblock 'Hello';pwsh.exe -Command "$scriptblock 'World'"
@Michael, есть ли что-нибудь полезное в /var/log/cloud-init-output.log? Вы пытались поместить некоторые операторы печати и т. д., Чтобы увидеть, где он случайно не работает? Что такое ваши пользовательские данные? Выполняется ли даже код PowerShell внутри <PowerShell>.. </PowerShell>?
@AdilHindistan, это экземпляр Windows, поэтому журналы находятся здесь: C:\ProgramData\Amazon\EC2Launch\log\agent.log Я обнаружил, что когда что-то пошло не так, обычно я даже не могу подключиться к экземпляр через SSM. Я использую CDK и класс UserData, поэтому мой скрипт корректно помещается в теги <powershell>
. Я знаю, что мой сценарий UserData попадает туда, потому что я могу найти его в экземпляре, как только у меня будет соединение.
Использовать два скрипта, один для установки powershell, а другой для запуска вашего кода?
@ Майкл - конечно, ты прав насчет местоположения. Честно говоря, ваш сценарий выглядит хорошо. Возможно, стоит рассмотреть возможность разделения кода PS7 на другой сценарий, как предложил Паоло. Вы можете включить команды для загрузки и запуска скрипта из s3. Вам нужен способ получения журналов, что означает, что вам сначала нужен функционирующий экземпляр, а затем запустить код pwsh. Как только вы выясните проблему, вы можете вернуть его обратно.
@AdilHindistan Спасибо! Эта идея загрузить второй скрипт с S3 и выполнить его через начальные данные пользователя оказалась немного проще и удобнее, чем размещение кода внутри блока скрипта (что действительно сработало).
Подход, который в конечном итоге сработал, заключался в том, чтобы иметь 2 разных сценария. Первый скрипт устанавливает PS7, а затем загружает второй скрипт с S3 и выполняет его с помощью PS7.
Пользовательские данные, выполненные с PS5:
#init.ps1
<powershell>
Invoke-WebRequest -Uri https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/PowerShell-7.3.1-win-x64.msi -OutFile PowerShell.msi
Start-Process msiexec.exe -ArgumentList '/i PowerShell.msi /quiet' -Wait
cd "C:\Program Files\PowerShell\7"
mkdir (Split-Path -Path 'C:/temp/setupGateway.ps1' ) -ea 0
Read-S3Object -BucketName 'my-bucket' -key 'setupGateway.ps1' -file 'C:/temp/setupGateway.ps1' -ErrorAction Stop
& "C:\Program Files\PowerShell\7\pwsh" "C:\temp\setupGateway.ps1"
</powershell>
<persist>true</persist>
Скрипт PS7, выполняемый отдельно:
# setup.ps1
Write-Output $PSVersionTable
Write-Output "Hello from PS7"
Все, что нужно сделать, чтобы это заработало, — убедиться, что вы скопировали скрипт setup.ps1
в папку S3. Это может быть достигнуто множеством различных способов в зависимости от остальной части вашей установки.
как насчет того, чтобы поместить код, который вы хотите запустить, в блок сценария (
{...}
), вызвать его с помощью оператора вызова (&
), а затем сделать то же самое с PowerShell 7, вызвав само приложение или войдя в pwsh в качестве интерактивной консоли.