Skip to content

Customer feedback | az vm run-command invoke with RunPowerShellScript does not fail with Exit 1 #29750

@dbradish-microsoft

Description

@dbradish-microsoft

This customer suggestion is being moved from MicrosoftDocs 4542. Please route to VM engineering team.

Reference command

az vm run-command invoke

Customer request summary

  1. Show the exit code from my script returned in the json if that's possible.
  2. Allow the command to accept --fail-on-non-zero, to propogate the exit code of az vm run-command-invoke back to me
  3. document some best practice for error handling around az vm run-command invoke with both bash and powershell.**

Feedback

I'm using the following form to run a powershell script on a virtual machine in Azure.

az vm run-command invoke  --command-id RunPowerShellScript --name win-vm -g my-resource-group \
    --scripts @test/bad.ps1 --parameters "arg1=somefoo" "arg2=somebar"

The trouble is, the returned JSON doesn't tell me that my script has exited 1:

param(
    [string]$arg1,
    [string]$arg2
)
Write-Host "[$Env:COMPUTERNAME] This is script should fail with parameters $arg1 and $arg2"
Exit 1

Yields:

{
  "value": [
    {
      "code": "ComponentStatus/StdOut/succeeded",
      "displayStatus": "Provisioning succeeded",
      "level": "Info",
      "message": "[win-vm] This is script should fail with parameters somefoo and somebar",
      "time": null
    },
    {
      "code": "ComponentStatus/StdErr/succeeded",
      "displayStatus": "Provisioning succeeded",
      "level": "Info",
      "message": "",
      "time": null
    }
  ]
}

When I throw an exception, I do get some error information in the second value object returned by the CLI:

param(
    [string]$arg1,
    [string]$arg2
)
Write-Host "[$Env:COMPUTERNAME] This is script should fail with parameters $arg1 and $arg2"
# https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-exceptions?view=powershell-5.1#working-with-exceptions
# https://powershellexplained.com/2017-04-07-all-dotnet-exception-list/#systemargumentexception
Write-Error -Exception ([System.ArgumentException]::new("[$Env:COMPUTERNAME] I am not a happy script with parameters $arg1 and $arg2")) -ErrorAction Stop
Exit 1

Yields:

{
  "value": [
    {
      "code": "ComponentStatus/StdOut/succeeded",
      "displayStatus": "Provisioning succeeded",
      "level": "Info",
      "message": "[win-vm] This is script should fail with parameters somefoo and somebar",
      "time": null
    },
    {
      "code": "ComponentStatus/StdErr/succeeded",
      "displayStatus": "Provisioning succeeded",
      "level": "Info",
      "message": "C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\1.1.18\\Downloads\\script0.ps1 : [win-vm] I am not a \nhappy script with parameters somefoo and somebar\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\1.1.18\\Downloads\\script0.ps1:8 char:1\n+ Write-Error -Exception ([System.ArgumentException]::new(\"[$Env:COMPUT ...\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    + CategoryInfo          : NotSpecified: (:) [Write-Error], ArgumentException\n    + FullyQualifiedErrorId : System.ArgumentException,script0.ps1\n ",
      "time": null
    }
  ]
}

**I think I'm asking for a few things:

💡 It would be nice if I could see the exit code from my script returned in the json if that's possible.
💡 What would be super duper is if I could pass --fail-on-non-zero, to propogate the exit code of az vm run-command-invoke back to me
📚 I think it would be helpful to document some best practice for error handling around az vm run-command invoke with both bash and powershell.**

I am sure I can cobble something together like checking result.value[1].message.length === 0 && result.value[1].code ==="ComponentStatus/StdOut/succeeded" but it feels fragile.

Here's what I feel I can safely assume:

results="bad.json"
az vm run-command invoke --command-id RunPowerShellScript --name win-vm -g win-rg --scripts @test/bad.ps1 --parameters "arg1=somefoo" "arg2=somebar" > $results
#!/bin/bash
results=$1
if [ ! -f "$results" ]; then
    echo "##[error] could not find $results"
    exit 1
fi

stdout_output=$(cat $results | jq -r '.value[0].message')
stdout_result=$(cat $results | jq -r '.value[0].code')
if [ "$stdout_result" = "ComponentStatus/StdOut/failed" ]; then
    echo "##[error] could not read stdout"
elif [ "$stdout_result" = "ComponentStatus/StdOut/succeeded" ]; then
    if [[ -n $stdout_output ]]; then
        echo $stdout_output
    fi
fi

stderr_output=$(cat $results | jq -r '.value[1].message')
stderr_result=$(cat $results | jq -r '.value[1].code')
if [ "$stderr_result" = "ComponentStatus/StdErr/failed" ]; then
    echo "##[error] could not read stderr"
elif [ "$stderr_result" = "ComponentStatus/StdErr/succeeded" ]; then
    if [[ -n $stderr_output ]]; then
        echo "##[error]$stderr_output"
    fi
fi

Page URL

https://learn.microsoft.com/en-us/cli/azure/vm/run-command?view=azure-cli-latest

Content source URL

https://github.com/MicrosoftDocs/azure-docs-cli/blob/main/latest/docs-ref-autogen/vm/run-command.yml

Metadata

Metadata

Labels

Auto-AssignAuto assign by botAzure CLI TeamThe command of the issue is owned by Azure CLI teamComputeaz vm/vmss/image/disk/snapshotSimilar-Issueact-observability-squadquestionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions