Function app Invoke-AzVMRunCommand on Linux

Thomas Murnane 56 Reputation points
2023-03-28T19:37:09.6333333+00:00

I was able to figure out how to run the Invoke-AzVMRunCommand to run a PowerShell script on a Windows VM to run azcopy.exe to download a file from blob storage to an azure windows VM, here is that question answered.

I've modified the function app to handle copying files to a Linux VM, here is my new Powershell Function app:

# Input bindings are passed in via param block.
param($QueueItem, $TriggerMetadata)

try {
   $FileName = $QueueItem['FileName']
   $PDB = $QueueItem['PDB']
   $EmailAddress = $QueueItem['EmailAddress']

   if ($PDB.Contains("LINUX")) { 
      $baseFolder = '/u01'
      $vmName = 'MY_LINUX_VM_NAME'
      $commandID = 'RunShellScript'
   }
   else { 
      $baseFolder = 'F:'
      $vmName = 'MY_WINDOWS_VM_NAME'
      $commandID = 'RunPowerShellScript'
   }

   $CopyToDumpScript = "$baseFolder/azcopy/CopyToDump.ps1"
   
   $StorageAccount = 'https://STORAGEACCOUNT.blob.core.windows.net/CONTAINER/'  
   $BlobURI = "{0}{1}" -f $StorageAccount, $FileName

   # Append arguments directly to the script path for positional argument passing
   $script = "$CopyToDumpScript $PDB $FileName $BlobURI $EmailAddress"

   # Create script file with arguments
   Out-File -FilePath "ScriptToRun.ps1" -InputObject $script
   
   $InvokeRunCmdOutput = Invoke-AzVMRunCommand `
      -ResourceGroupName 'MY_RESOURCE_GROUP' `
      -Name "$vmName" `
      -CommandId "$commandID" `
      -ScriptPath 'ScriptToRun.ps1'

   $Output = $InvokeRunCmdOutput.Value[0].Message
   Write-Host "InvokeCommandOutput = $Output"
   
   Remove-Item -Path 'ScriptToRun.ps1'

   # Queue to notify that file has been copied to VM
   #Push-OutputBinding -Name Msg -Value $QueueItem
}
catch {
   Write-Host $_.Exception.Message
}

Here is the script on the Linux VM "/u01/azcopy/CopyToDump.ps1"

#!/usr/bin/pwsh

param(
  [string]$PDB,
  [string]$FileName,
  [string]$BlobURI,
  [string]$EmailAddress
)

$SAS = 'SAS TOKEN - TRIED WITH AND WITHOUT'

$logFile = "/u01/azcopy/log.txt"
$downloadFlder = "/u01/azcopy/downloads"
$azcopy = "/u01/azcopy/azcopy"

Function Write-Log {
   param(
      [Parameter(Mandatory = $true)][string] $message,
      [Parameter(Mandatory = $false)]
      [ValidateSet("INFO", "WARN", "ERROR")]
      [string] $level = "INFO"
   )
   $timestamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")    
   Add-Content -Path $logFile -Value "$timestamp [$level] - $message"
}

$DownloadFile = "$downloadFlder/$FileName"
$Destination = "$dumpFolder/$folder"

try
{
  Write-Log -level INFO -message "Downloading: $BlobURI"  

  # read somewhere that Linux requires single quotes around args
  $blogArg = "'{0}?{1}'" -f $BlobURI, $SAS # tried this with and without SAS
  $fileArg = "'{0}'" -f $DownloadFile
  
  Write-Log -level INFO -message "Running: $azcopy copy $blogArg $fileArg --overwrite=ifsourcenewer --check-md5=FailIfDifferent --recursive"  

  & $azcopy copy $blogArg $fileArg --overwrite=ifsourcenewer --check-md5=FailIfDifferent --recursive

  Write-Log -level INFO -message "Done!"
} 
catch 
{
  Write-Log -level ERROR -message  "Error running script"
  Write-Log -level ERROR -message  "$_.Message"
  exit -1
}

I cannot seem to get any output from the azcopy cmd, I just get a return success in the function app and I see the messages in the log "Running:..." and "Done!" like a second after, which tends to mean this does nothing. I would expect it to throw some sort of error or warning but nothing

If I copy the command from the logfile verbatim - and run it on the cmdline, it runs with no issue. I'm assuming this is most likely due to user permissions, but wouldn't the azcopy throw an error or warning of some sort? Any idea as to what is going on?
Thanks

Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
4,898 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Sedat SALMAN 13,740 Reputation points
    2023-03-28T19:49:49.96+00:00

    It's possible that the issue is related to the execution policy in PowerShell. By default, PowerShell execution policy is set to Restricted, which prevents the execution of any scripts. You may need to change the execution policy to allow scripts to run.

    You can try setting the execution policy to RemoteSigned or Unrestricted by running the following command in your PowerShell script:

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process

    Alternatively, you can try running the azcopy command directly from the Linux command line using the same parameters to see if you get any output or errors. If it works from the command line, but not from the PowerShell script, then it's likely an issue with the PowerShell execution policy.

    Another possibility is that the azcopy command is not installed or not in the system path on the Linux VM. You can try specifying the full path to the azcopy executable in your PowerShell script to ensure that it's being called correctly.

    0 comments No comments

  2. Thomas Murnane 56 Reputation points
    2023-03-28T21:48:34.1866667+00:00

    I got this working by using the SAS token and NOT adding single quotes around the arguments - I can't seem to find where I saw this in the online documentation when running on Linux. I was using system identity and didn't need to use the SAS token on the windows vm and didn't think I needed it for the Linux vm. I'm assuming this has something to do with the way the permissions are on the Linux side of things.

    
      # read somewhere that Linux requires single quotes around args
      $blogArg = "'{0}?{1}'" -f $BlobURI, $SAS # tried this with and without SAS
      $fileArg = "'{0}'" -f $DownloadFile
    
      # Changed to 
      $blogArg = "{0}?{1}" -f $BlobURI, $SAS
      #and just used  $DownloadFile
    
    & $azcopy copy $blogArg $DownloadFile --overwrite=ifsourcenewer --check-md5=FailIfDifferent --recursive
    
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.