如何在Azure Function中安装PowerShell模块

11

我需要 AWS 模块,它可以从 PS-Gallery 获得,但是当我尝试在 Azure Function 中运行安装步骤时,它无法正常工作。 -verbose 参数标记不会将任何内容写入控制台。

在 Azure 函数中获取和使用其他 PowerShell 模块的正确方法是什么?

函数代码

[Console]::WriteLine("PowerShell Timer trigger function executed at:$(get-date)");
if (-not (Get-Module -Name "AWSPowerShell")) {
[Console]::WriteLine("AWSPowerShell not installed");
Install-Module -Name AWSPowerShell -Scope CurrentUser -ErrorAction Continue -Verbose
}
if (-not (Get-Module -Name "AWSPowerShell")){
[Console]::WriteLine("AWSPowerShell install step failed");
}

函数日志

2016-06-09T11:24:31.108 Function started (Id=e09be687-2e13-4754-942e-eab75c8516e5)
2016-06-09T11:24:32.788 Powershell Timer trigger function executed at:06/09/2016 11:24:32
AWSPowerShell not installed
AWSPowerShell install step failed
2016-06-09T11:24:32.788 Function completed (Success, Id=e09be687-2e13-4754-942e-eab75c8516e5)

更新

根据@travis的回答,我添加了建议的代码,包括NuGet包管理器行。但仍然无法解决问题。我添加了另一行调试代码,并发现没有模块提供程序,即使尝试添加NuGet后也是如此!

修改后的代码

[Console]::WriteLine("Powershell Timer trigger function executed at:$(get-date)");

Get-PackageProvider -Name nuget -ForceBootstrap

$pkg=Get-PackageProvider -ListAvailable
if ($pkg.Count -lt 1){ [Console]::WriteLine("No providers")}

if (-not (Get-Module -listavailable -Name "AWSPowerShell")) {
    [Console]::WriteLine("AWSPowerShell not installed");
    Install-Module -Name AWSPowerShell -Scope CurrentUser -ErrorAction Continue -Verbose -force
}

if (-not (Get-Module -listavailable -Name "AWSPowerShell")){
    [Console]::WriteLine("AWSPowerShell install step failed");
}

Import-Module AWSPowerShell

修订日志

2016-06-09T17:54:03.859 Powershell Timer trigger function executed at:06/09/2016 17:54:02
No providers
AWSPowerShell not installed
AWSPowerShell install step failed
2016-06-09T17:54:03.859 Function completed (Success, Id=80efb9fc-5e91-45f9-ab58-3b71fcd764af)
4个回答

13
Azure Functions对PowerShell脚本的支持目前处于实验阶段。以下场景得到了支持:
1. Azure Functions将能够支持客户自带模块。这些模块将位于名为“modules”的文件夹中,该文件夹位于PowerShell脚本所在的同一目录中。在示例函数的Kudu控制台中,目录结构如下:

enter image description here

  1. 我们不支持客户使用 Install-Module 命令来安装他们自己的模块,但是客户可以将他们的模块上传到 modules 文件夹中。

  2. modules 文件夹中的所有模块都将自动加载,因此客户无需显式使用 Import-Module 命令。

  3. 我们将支持 脚本二进制清单 模块。这些模块将驻留在 modules 文件夹内的平面结构中。一个示例布局如下:

    enter image description here

针对您所要实现的内容,以下是一些建议的步骤,以确保加载 AWSPowerShell 模块。

  1. 在开发计算机上安装 AWSPowerShell。您需要上传\AWSPowerShell\3.3.5.0下的所有内容。

  2. 使用Kudu界面,将AWSPowerShell的已安装依赖项上传到位于函数目录中的modules文件夹中。要这样做,请打开函数应用程序的Portal UI并单击“Function App Settings”按钮。

  3. 接下来,单击“Go to Kudu”按钮启动Kudu控制台。您应该看到类似以下内容的快照:

    enter image description here

  4. 在cmd控制台提示符中,导航到您的函数文件夹,创建一个modules目录,并将所有内容从\AWSPowerShell\3.3.5.0上传到modules目录中。

您最终应该得到一个模块文件夹,其中包含类似于下面快照的文件列表:

enter image description here

5. 运行您的函数。例如,给定以下用于我的函数的脚本,
``` if (-not (Get-Module -Name "AWSPowerShell")) { Write-Output "AWSPowerShell not installed"; } else { Write-Output "AWSPowerShell installed"; } ```
执行时,日志输出如下:
2016-10-11T18:26:01.486 Function started (Id=582b69aa-6236-436d-81c5-c08ada8ae674)
2016-10-11T18:26:03.267 Loaded modules:
/AWSPowerShell/modules/AWSPowerShell.psd1
/AWSPowerShell/modules/AWSPowerShell.dll
/AWSPowerShell/modules/AWSSDK.APIGateway.dll
/AWSPowerShell/modules/AWSSDK.ApplicationAutoScaling.dll
/AWSPowerShell/modules/AWSSDK.ApplicationDiscoveryService.dll
/AWSPowerShell/modules/AWSSDK.AutoScaling.dll
/AWSPowerShell/modules/AWSSDK.AWSMarketplaceCommerceAnalytics.dll
/AWSPowerShell/modules/AWSSDK.AWSMarketplaceMetering.dll
/AWSPowerShell/modules/AWSSDK.AWSSupport.dll
/AWSPowerShell/modules/AWSSDK.CertificateManager.dll
/AWSPowerShell/modules/AWSSDK.CloudFormation.dll
/AWSPowerShell/modules/AWSSDK.CloudFront.dll
/AWSPowerShell/modules/AWSSDK.CloudHSM.dll
/AWSPowerShell/modules/AWSSDK.CloudSearch.dll
/AWSPowerShell/modules/AWSSDK.CloudSearchDomain.dll
/AWSPowerShell/modules/AWSSDK.CloudTrail.dll
/AWSPowerShell/modules/AWSSDK.CloudWatch.dll
/AWSPowerShell/modules/AWSSDK.CloudWatchEvents.dll
/AWSPowerShell/modules/AWSSDK.CloudWatchLogs.dll
/AWSPowerShell/modules/AWSSDK.CodeCommit.dll
/AWSPowerShell/modules/AWSSDK.CodeDeploy.dll
/AWSPowerShell/modules/AWSSDK.CodePipeline.dll
/AWSPowerShell/modules/AWSSDK.CognitoIdentity.dll
/AWSPowerShell/modules/AWSSDK.CognitoIdentityProvider.dll
/AWSPowerShell/modules/AWSSDK.ConfigService.dll
/AWSPowerShell/modules/AWSSDK.Core.dll
/AWSPowerShell/modules/AWSSDK.DatabaseMigrationService.dll
/AWSPowerShell/modules/AWSSDK.DataPipeline.dll
/AWSPowerShell/modules/AWSSDK.DeviceFarm.dll
/AWSPowerShell/modules/AWSSDK.DirectConnect.dll
/AWSPowerShell/modules/AWSSDK.DirectoryService.dll
/AWSPowerShell/modules/AWSSDK.DynamoDBv2.dll
/AWSPowerShell/modules/AWSSDK.EC2.dll
/AWSPowerShell/modules/AWSSDK.ECR.dll
/AWSPowerShell/modules/AWSSDK.ECS.dll
/AWSPowerShell/modules/AWSSDK.ElastiCache.dll
/AWSPowerShell/modules/AWSSDK.ElasticBeanstalk.dll
/AWSPowerShell/modules/AWSSDK.ElasticFileSystem.dll
/AWSPowerShell/modules/AWSSDK.ElasticLoadBalancing.dll
/AWSPowerShell/modules/AWSSDK.ElasticLoadBalancingV2.dll
/AWSPowerShell/modules/AWSSDK.ElasticMapReduce.dll
/AWSPowerShell/modules/AWSSDK.Elasticsearch.dll
/AWSPowerShell/modules/AWSSDK.ElasticTranscoder.dll
/AWSPowerShell/modules/AWSSDK.GameLift.dll
/AWSPowerShell/modules/AWSSDK.IdentityManagement.dll
/AWSPowerShell/modules/AWSSDK.ImportExport.dll
/AWSPowerShell/modules/AWSSDK.Inspector.dll
/AWSPowerShell/modules/AWSSDK.IoT.dll
/AWSPowerShell/modules/AWSSDK.IotData.dll
/AWSPowerShell/modules/AWSSDK.KeyManagementService.dll
/AWSPowerShell/modules/AWSSDK.Kinesis.dll
/AWSPowerShell/modules/AWSSDK.KinesisAnalytics.dll
/AWSPowerShell/modules/AWSSDK.KinesisFirehose.dll
/AWSPowerShell/modules/AWSSDK.Lambda.dll
/AWSPowerShell/modules/AWSSDK.MachineLearning.dll
/AWSPowerShell/modules/AWSSDK.MobileAnalytics.dll
/AWSPowerShell/modules/AWSSDK.OpsWorks.dll
/AWSPowerShell/modules/AWSSDK.RDS.dll
/AWSPowerShell/modules/AWSSDK.Redshift.dll
/AWSPowerShell/modules/AWSSDK.Route53.dll
/AWSPowerShell/modules/AWSSDK.Route53Domains.dll
/AWSPowerShell/modules/AWSSDK.S3.dll
/AWSPowerShell/modules/AWSSDK.SecurityToken.dll
/AWSPowerShell/modules/AWSSDK.ServiceCatalog.dll
/AWSPowerShell/modules/AWSSDK.SimpleEmail.dll
/AWSPowerShell/modules/AWSSDK.SimpleNotificationService.dll
/AWSPowerShell/modules/AWSSDK.SimpleSystemsManagement.dll
/AWSPowerShell/modules/AWSSDK.SimpleWorkflow.dll
/AWSPowerShell/modules/AWSSDK.Snowball.dll
/AWSPowerShell/modules/AWSSDK.SQS.dll
/AWSPowerShell/modules/AWSSDK.StorageGateway.dll
/AWSPowerShell/modules/AWSSDK.WAF.dll
/AWSPowerShell/modules/AWSSDK.WorkSpaces.dll
/AWSPowerShell/modules/log4net.dll
/AWSPowerShell/modules/AWSPowerShellCompleters.psm1
2016-10-11T18:27:21.265 AWSPowerShell installed
2016-10-11T18:27:21.464 Function completed (Success, Id=582b69aa-6236-436d-81c5-c08ada8ae674)

注意:由于所有模块都是在运行时加载的,因此该功能需要一段时间才能完成。
需要记住的是,与大多数IaaS设置不同,Azure函数在多租户环境中执行。因此,存在以下已知注意事项:
1. 我们的基础架构会防止任何执行我们认为是安全风险的低级API的函数(例如交互式模式、主机凭据访问、注册表编辑等)。如果您使用的PowerShell脚本或模块调用了任何这些被阻止的API,则无法在函数中执行这些工作负载。尽管如此,我们的目标是支持尽可能多的场景,因此我们将根据客户需求量优先解除阻止的情况。
2. 我们当前在基础架构中安装了PowerShell版本4.0和Azure PowerShell 1.4。我们将很快升级这些版本。随着我们在Azure函数中增加对PowerShell的支持,模块套件可能会随时间升级或添加。这些预安装的模块可能会与您现有的模块发生冲突。

这对于设置初始代码非常有帮助。但是它使本地开发变得很麻烦。在本地运行./run.ps1时,它没有本地加载的DLL或我的脚本模块。因此,我必须想出一些防御性的方法来在本地开发中运行脚本...还没有想出来。 - Rick Glos
“modules”文件夹只是一个方便的功能。您可以将其重命名为“Modules”或任何其他名称,并将DLL放入其中。然后在run.ps1脚本中使用Import-Module cmdlet。 - Ling Toh
2
此外,您还可以将自定义模块目录上移,以便在同一函数应用程序中的函数之间共享相同的路径。 - Ling Toh
我现在确实看到了,我可以使用 if (-not (Get-Module -Name "ScriptName")) 来检查脚本模块。我仍在努力尝试通过模块中的 Add-Type 可选加载 DLL。 - Rick Glos

1
关于更新azurerm powershell模块,有很多模块需要更新到最新版本4.1.0,如果我们上传将会成为一个放在平级目录下的问题。
C:\Program Files (x86)\Microsoft SDKs\Azure\PowerShell\ResourceManager\AzureResourceManager 包含46个文件夹。

1

你需要通过添加 -listavailableget-module 命令来确保查找所有模块,而不仅仅是已加载的模块。

在非交互环境中使用 install-module 时,您可能需要引导 nuget。命令是:Get-PackageProvider -Name nuget -ForceBootstrap

如果您安装的存储库未经信任,则可能需要强制执行 install-module 命令。

示例

[Console]::WriteLine("Powershell Timer trigger function executed at:$(get-date)");

if (-not (Get-Module -listavailable -Name "AWSPowerShell")) {
    [Console]::WriteLine("AWSPowerShell not installed");
    Install-Module -Name AWSPowerShell -Scope CurrentUser -ErrorAction Continue -Verbose -force
}

if (-not (Get-Module -listavailable -Name "AWSPowerShell")){
    [Console]::WriteLine("AWSPowerShell install step failed");
}

FYI: 在自动化脚本中,[Console]::WriteLine 不被视为PowerShell的良好实践。尝试使用 Write-Verbose,你可以像这样强制它:Write-Verbose -message 'my message' -verbose

我最初使用的是write-host,但WriteLine是微软编写的,所以我选择了他们的方法,假设这是最佳实践/正确的解决方案。我想这里适用于“假设会导致错误”这句格言! ;) - Steph Locke
我不知道这被用在哪里。Console.WriteHost 可能在那里被用于特定的原因,但如果是这样的话,我想更好地理解。我的 Twitter 信息在我的个人资料中。我们应该在这里保持主题。 - TravisEz13
1
看起来我可能无法在 Azure Functions 的 PowerShell 上下文中添加软件包提供程序 :-/ - Steph Locke

0

我怀疑原因是您没有指定要从哪个位置加载模块。当前的$env:PSModulePath列出如下:

WindowsPowerShell\Modules;
D:\Program Files (x86)\WindowsPowerShell\Modules; D:\Windows\system32\WindowsPowerShell\v1.0\Modules\;
d:\Program Files\Microsoft Security Client\MpProvider\;
D:\Program Files\Microsoft Message Analyzer\PowerShell\;
D:\Program Files\WindowsPowerShell\Modules\;
D:\Program Files (x86)\MicrosoftSDKs\Azure\PowerShell\ResourceManager\AzureResourceManager\;
D:\Program Files (x86)\Microsoft SDKs\Azure\PowerShell\ServiceManagement\;
D:\Program Files (x86)\Microsoft SDKs\Azure\PowerShell\Storage\

我无法完全确定它是从哪里引用第一个,所以我无法将它们放在那里。因此,我改为使用了这个组合。

$env:PSModulePath = $env:PSModulePath + ";d:\home\modules\"

import-module azured 
$out = Deploy-Template
[Console]::WriteLine($out)
Out-File -Encoding Ascii $Env:res -inputObject $out

这将加载位于d:\ home \ modules的模块,并按预期工作

Get-PackageProvider -Name nuget -ForceBootstrap无法正常工作的原因是未安装PackageManagement模块。但是,nuget已经安装。您需要直接与{{link1:kudu}}交互以此方式安装软件包。

我很高兴看到我不是唯一被函数折磨的人;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接