If you run Linux VM’s on Azure, then you at some point will want to call a Custom Script Extension that runs your own script (bash etc) to perform some operations within the virtual machine.
There are a few options for doing this including of course using chef and puppet, or as is documented here simply calling a Custom Script Extension with your own script.
When experimenting with doing this I found a lot of the documentation describing how to do this was out of date principally because it did not use the “customScript” extension type (publisher Microsoft.Azure.Extensions).
Note for Windows VM’s you use a different custom extension type “CustomScriptExtension” (publisher Microsoft.Compute) – see the commented section in the middle of the PowerShell script below
Listed below is the PowerShell to execute a command “command2.sh” which is stored as a blob in an Azure storage account in a container named “myscripts”. The PowerShell also grabs any output (stdout) from command2.sh – (getting stderr would be done in a similar way)
This script assumes you are using ARM and have previously logged into Azure from PowerShell (login-AzureRmAccount) and if required set the default subscription (Select-AzureRmSubscription)
$rg='your-resource-group' $vmname='yourvm' $storageaccountname='your-storage-account-name' $cont='myscripts' $Extensionname='customScript' $vm = Get-AzurermVM -Name $vmname -ResourceGroupName $rg # get the storage key $key = (Get-AzureRmStorageAccountKey -Name $storageaccountname -ResourceGroupName $rg).value[0] if (!$key) { write-output "Could not find a storage key" exit } # # check if there's an existing custom script extension # if there is remove it - your only allowed one at a time # $extname = ($VM.Extensions | Where { $_.VirtualMachineExtensionType -eq 'customScript' }).name if ($extname) { write-output "removing existing extension: $extname" remove-azurermvmextension -name $extname -ResourceGroupName $rg -VMName $vmname -force write-output "removed - waiting 10 seconds ...." start-sleep -Seconds 10 } # get extension types # for windows use: # Get-AzureRmVMExtensionImage -Location westeurope -PublisherName Microsoft.Compute -Type CustomScriptExtension # for Linux use: # Get-AzureRmVMExtensionImage -Location westeurope -PublisherName Microsoft.Azure.Extensions -Type customScript # # #For Linux: # # Setup for call to Set-AzureRmExtension # $TheURI = "https://$storageaccountname.blob.core.windows.net/myscripts/command2.sh" $Settings = @{"fileUris" = @($TheURI); "commandToExecute" = "./command2.sh"}; $ProtectedSettings = @{"storageAccountName" = $storageaccountname; "storageAccountKey" = $key}; # Set-AzureRmVMExtension -ResourceGroupName $rg -Location $vm.location -VMName $vmname -Name "customScript" -Publisher "Microsoft.Azure.Extensions" -Type "customScript" -TypeHandlerVersion "2.0" -Settings $Settings -ProtectedSettings $ProtectedSettings # if ($?) { write-output "set extension ok" # # Get script extension output # $extout=((Get-AzureRmVM -Name $VMName -ResourceGroupName $RG -Status).Extensions | Where-Object {$_.Name -eq $ExtensionName}).statuses.Message # # Parse the stdout # $stdout=$extout.substring($extout.indexof('[stdout]')+8,$extout.indexof('[stderr]')-$extout.indexof('[stdout]')-8) $stdout=$stdout.trim() write-output "stdout from command: $settings.commandToExecute" $stdout } else { write-output "set extension problem?" } # #
The above will be particularly useful when developing runbooks that are called as steps in a Azure Site Recovery plan.
If Multiple Linux VM’s are involved in the recovery plan it’s often necessary to query hostnames, assigned IP addresses or other information from Virtual Machine A and feed that information as parameter into Virtual Machine B etc. so it can correctly configure itself with Virtual Machine A’s information as part of the failover process.
Eg. As part of the failover plan – custom script extension 1 runs on VM1 (database server) and returns the hostname/ip address etc – which are then passed as parameters into custom extension script 2 run by VM2 (web server) which using the script reconfigures itself to use the new hostname/ip address given to the database server as it failed over into Azure, as this may be different to what was used ‘on-premise’ (or from the source Azure region if your using Azure to Azure ASR).
Thank you! This worked perfectly when other attempts failed.
LikeLike
Worked like a charm. I was trying to do it with a Hybrid worker group but was unable to achieve the functionality. This worked just fine.
LikeLike