Azure Custom Script Extension의 powershell 함수에 문자열을 매개 변수로 전달하려고 할 때 "잘못된 배열이 전달되었습니다 ..."

Csamleong

내 시나리오 : JSON 문자열을 매개 변수로 Azure 사용자 지정 스크립트 확장에 전달하고 스크립트를 실행하여 VM 구성을 업데이트해야합니다. 그리고 다음과 같은 오류가 발생했습니다....ExecuteUpdateConfig.ps1 : Invalid array passed in, ']' expected...

내가 시도한 것 :

  1. 모든 것이 문자열 유형인지 확인하기 위해 $ variable.GetType ()을 사용합니다.

  2. 스크립트 자체를 테스트하기 위해 Azure 사용자 지정 스크립트 확장을 사용하지 않고 스크립트를 실행하려고했습니다. 그리고 실제로 작동합니다. 나는 모든 문자열을 전달하고 있는데, "Array"는 어디에서 오는가?

    . ("D:\Utilities\ExecuteUpdateConfig.ps1") -DsnConfigsAsString $dsnconfigs -WebConfigsAsString $webconfigs
    
  3. 문제는 스크립트를 실행하고 매개 변수를 전달하는 방법 일 수 있습니다. 나는 지역에서 두 가지 방법을 시도했다.

ㅏ. 도트 소싱 작동 :

. ("D:\Utilities\ExecuteUpdateConfig.ps1") -DsnConfigsAsString $dsnconfigs -WebConfigsAsString $webconfigs

비. 이 구문은 작동하지 않으며 언급 된 오류가 발생합니다.

powershell.exe -ExecutionPolicy Unrestricted -Command "D:\Utilities\\ExecuteUpdateConfig.ps1 -DsnConfigsAsString $dsnconfigs -WebConfigsAsString $webconfigs"

JSON 문자열을 생성하고 사용자 지정 스크립트 확장의 스크립트에 문자열을 전달하는 방법 :

$vm = @{ }
$vm | Add-Member WebConfigs @()
$vm | Add-Member WebConfigs @()
$vm | Add-Member WebConfigs @()

$vm.WebConfigs += ([PSCustomObject]@{
    Path           = "C:\WindowsAzure\Packages\CommonAgentConfig.config"
    Node           = "configSections"
    ChildNode      = "section"
    AttributeKey   = "name"
    AttributeValue = "microsoft.windowsAzure.guestAgent.configuration"
    UpdatedValue   = "SamLeong"
    EncryptedValue = $false
})

##convert to json string 
$webconfigs = ConvertTo-Json @($vm.WebConfigs )
$dsnconfigs = ConvertTo-Json @($vm.DsnConfigs)
$registryconfigs = ConvertTo-Json @()

##Generate a VM with custom script extension using ARM template
##dsnConfigs, webconfigs and registryConfigs are my JSON string
##password,fileuri, resourcegorupname not related to the problems are not shown here
New-AzResourceGroupDeployment `
-ResourceGroupName $resourceGroupName `
-TemplateFile ".\customscriptext.json" `
-adminUsername "tester" `
-adminPassword $adminPassword `
-vmName "test16" `
-dsnConfigs $dsnconfigs -webConfigs $webconfigs -FileUrl $fileUrl `  
-dnsLabelPrefix "samtest16"

ARM 템플릿에서 params와 PowerShell 명령을 CommandToExecute에 연결하고 ARM 템플릿의 매개 변수 섹션에서 "문자열"로 정의했습니다.

    {
        "apiVersion": "2018-06-01",
        "type": "Microsoft.Compute/virtualMachines/extensions",
        "location": "[resourceGroup().location]",
        "name": "[concat(parameters('vmName'),'/installcustomscript')]",
        "dependsOn": [
            "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"
        ],
        "tags": {
            "displayName": "config-app"
        },
        "properties": {
            "publisher": "Microsoft.Compute",
            "type": "CustomScriptExtension",
            "typeHandlerVersion": "1.10",
            "autoUpgradeMinorVersion": true,
            "settings": {
                "fileUris": "[parameters('FileUrl')]"
            },
            "protectedSettings": {
                "commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -File ExecuteUpdateConfig.ps1', ' -DsnConfigsAsString ', parameters('dsnConfigs'), ' -WebConfigsAsString ', parameters('webConfigs'))]",
                "storageAccountName": "xxxxxxxxxxxxxxxxxxxxxxxxx",
                "storageAccountKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
            }
        }
    }

그리고 내 ExecuteUpdateConfig.ps1 스크립트에서 :

param([string] $DsnConfigsAsString, [string] $WebConfigsAsString )


try {
    $DsnConfigs = $DsnConfigsAsString | Out-String | ConvertFrom-Json
    $WebConfigs = $WebConfigsAsString | Out-String | ConvertFrom-Json

    #other execution logics follow...
    foreach ($dsn in $DsnConfigs) { ##read the dsn object and update  } 
    foreach ($webConfig in $WebConfigs) { ##read the webconfig object and update }
}catch{
    Write-Error "$($_.Exception.Message)"
    throw "Error in updateAllSettings" 
}

전체 오류 :

Microsoft.Compute/virtualMachines/extensions 'samtest17/installcustomscript' failed 
with message '{
  "status": "Failed",
  "error": {
    "code": "ResourceDeploymentFailure",
    "message": "The resource operation completed with terminal provisioning state      
'Failed'.",
    "details": [
      {
        "code": "VMExtensionProvisioningError",
        "message": "VM has reported a failure when processing extension
'installcustomscript'. Error message: \"Command execution finished, but failed
because it returned a non-zero exit code of: '1'. The command had an error output of:  
'C:\\Packages\\Plugins\\Microsoft.Compute.CustomScriptExtension\\1.10.5\\Downloads\\0\ 
\\r\nExecuteUpdateConfig.ps1 : Invalid array passed in, ']' expected. (3): [\r\n    + 
CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorExcep \r\n
tion\r\n    + FullyQ...' For more information, check the instance view by executing    
Get-AzVmssVm or Get-AzVm (https://aka.ms/GetAzVm). These commands can be executed      
using CloudShell (https://aka.ms/CloudShell)\"\r\n\r\nMore information on
troubleshooting is available at https://aka.ms/VMExtensionCSEWindowsTroubleshoot "     
      }
    ]
  }
}'
At D:\Scripts\Testing\TestCustomScript.ps1:58 char:1
+ New-AzResourceGroupDeployment `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-AzResourceGroupDeployment], Exce  
   ption
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implem  
   entation.NewAzureResourceGroupDeploymentCmdlet

New-AzResourceGroupDeployment : 10:42:42 AM - VM has reported a failure when 
processing extension 'installcustomscript'. Error message: "Command execution 
finished, but failed because it returned a non-zero exit code of: '1'. The command     
had an error output of:
'C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.10.5\Downloads\0\       
ExecuteUpdateConfig.ps1 : Invalid array passed in, ']' expected. (3): [
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorExcep
   tion
    + FullyQ...' For more information, check the instance view by executing
Get-AzVmssVm or Get-AzVm (https://aka.ms/GetAzVm). These commands can be executed      
using CloudShell (https://aka.ms/CloudShell)"
More information on troubleshooting is available at
https://aka.ms/VMExtensionCSEWindowsTroubleshoot
At D:\Scripts\Testing\TestCustomScript.ps1:58 char:1
+ New-AzResourceGroupDeployment `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-AzResourceGroupDeployment], Exce  
   ption
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implem  
   entation.NewAzureResourceGroupDeploymentCmdlet

New-AzResourceGroupDeployment : 10:42:42 AM - Template output evaluation skipped: at   
least one resource deployment operation failed. Please list deployment operations for  
details. Please see https://aka.ms/DeployOperations for usage details.
At D:\Scripts\Testing\TestCustomScript.ps1:58 char:1
+ New-AzResourceGroupDeployment `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-AzResourceGroupDeployment], Exce  
   ption
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implem  
   entation.NewAzureResourceGroupDeploymentCmdlet

New-AzResourceGroupDeployment : 10:42:42 AM - Template output evaluation skipped: at 
least one resource deployment operation failed. Please list deployment operations for  
details. Please see https://aka.ms/DeployOperations for usage details.
At D:\Scripts\Testing\TestCustomScript.ps1:58 char:1
+ New-AzResourceGroupDeployment `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-AzResourceGroupDeployment], Exce  
   ption
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implem  
   entation.NewAzureResourceGroupDeploymentCmdlet


Mclayton

(내 댓글에서 확장 ^^^)

도트 소싱이 스크립트에서 작동하지만 powershell.exe 호출이 실패하는 두 가지 이유가 있습니다.

  • 점 소싱 스크립트는 기존 powershell 세션 내에서 실행되고 값을 변수 참조로 스크립트에 전달하지만 powershell.exe를 호출하면 명령 줄 파서가 문자열 변수 을 해석 할 수 있습니다.

  • $ dsnConfigs 변수에 줄 바꿈 및 기타 문자 (예 : "')가 있으며, 예상대로 명령 줄에서 해석되지 않습니다.

시연하려면 :

PS> Set-Content "myscript.ps1" "param([string] `$JsonString)`r`nwrite-host `$JsonString; `$myVar = ConvertFrom-Json `$JsonString"

PS> $myJson = ConvertTo-Json -InputObject @()
PS> . .\myScript.ps1 $myJson
[

]

PS> powershell .\myscript.ps1 $myJson
[
ConvertFrom-Json : Invalid array passed in, ']' expected. (1): [
At C:\src\scratch\myscript.ps1:2 char:34
+ write-host $JsonString; $myVar = ConvertFrom-Json $JsonString
+                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

-CompressConvertTo-Json과 함께 스위치를 사용하여 줄 바꿈을 제거 할 수 있습니다 .

PS> $myJson = ConvertTo-Json -InputObject @() -Compress
PS> powershell .\MyScript.ps1 $myJson
[]

하지만 여전히 명령 줄 파서의 다른 문제로부터 당신을 구할 수는 없습니다.

PS> $myJson = ConvertTo-Json -InputObject @("aaa") -Compress
PS> powershell .\MyScript.ps1 $myJson
[aaa]
ConvertFrom-Json : Invalid JSON primitive: aaa.
At C:\src\scratch\myscript.ps1:2 char:34
+ write-host $JsonString; $myVar = ConvertFrom-Json $JsonString
+                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

이 답변에 따라- 명령 줄을 통해 JSON 문자열 전달-json 문자열을 base64로 인코딩하고 base64 문자열을 매개 변수로 전달한 다음 스크립트 내에서 디코딩 할 수 있습니다.

PS> $myJson = ConvertTo-Json -InputObject @("aaa")
PS> $utf8   = [System.Text.Encoding]::UTF8.GetBytes($myJson)
PS> $base64 = [System.Convert]::ToBase64String($utf8)
PS> powershell .\MyScript.ps1 $base64
WyJhYWEiXQ==
["aaa"]

myscript.ps1을 사용하면 이제 base64 문자열을 원래 json으로 디코딩하기 위해 다음과 같이 보입니다.

myscript.ps1

param([string] $Base64Json)
write-host $Base64Json;

$utf8 = [System.Convert]::FromBase64String($Base64Json);
$json = [System.Text.Encoding]::UTF8.GetString($utf8);
write-host $json

$myVar = ConvertFrom-Json $json

도움이 되었기를 바랍니다...

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관