You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Function App调用Invoke-AzVMRunCommand时参数为空的问题

问题:Invoke-AzVMRunCommand传参为空的排查与解决

问题现象

队列触发的PowerShell Function App调用Invoke-AzVMRunCommand执行Azure VM上的脚本时,脚本能正常启动,但始终接收不到传入的参数。

Function App代码

# Input bindings are passed in via param block.
param($QueueItem, $TriggerMetadata)
$ErrorActionPreference = "Stop"
try 
{
  $SasToken = $Env:SasToken

  $PDB = $QueueItem['PDB']
  $FileName = $QueueItem['FileName']

  $StorageAccount = 'https://STORAGENAME.blob.core.windows.net/CONTAINER/'
  $BlobURI = "{0}{1}{2}" -f $StorageAccount, $FileName, $sasToken

  $ScriptPath = "F:\azCopy\CopyToDump.ps1"
  $ScriptFile = "CopyToDump.ps1"

  $params = @{
    "PDB" = $PDB;
    "BlobURI" = $BlobURI
  }

  # 直接用"-ScriptPath $ScriptPath"时提示找不到路径,参考帖子后用了Out-File,但不清楚原理
  Out-File -InputObject $ScriptPath -FilePath ScriptToRun.ps1

  Invoke-AzVMRunCommand `
    -ResourceGroupName 'RESOURCE_GROUP' `
    -VMName 'VM_NAME' `
    -CommandId 'RunPowerShellScript' `
    -ScriptPath ScriptToRun.ps1 `
    -Parameter @{ PDB = $PDB; BlobURI = $BlobURI }

  Remove-Item -Path ScriptToRun.ps1
  Write-Host "Done"
} catch {
  $_.Exception.Message
}

VM上的目标脚本(CopyToDump.ps1)

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

$logFile = "F:\azcopy\Info.txt"
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"
}

try
{
  $folder = switch ($PDB)
  {
    'QA' {'094D2AA1A909459BA36ABEEA7F7732F6'}
    'DEV' {'0B2305B6305547F389F96C800630CD21'}
  }

  $dpdump = "F:\app\oracle\admin\hs\dpdump\$folder"

  Write-Log -level INFO -message  "---------------------------"
  Write-Log -level INFO -message  "Copying:  $BlobURI"
  Write-Log -level INFO -message  "To folder $dpdump"
  Write-Log -level INFO -message  "---------------------------"
  Write-Log -level INFO -message  "F:\azCopy\AzCopy.exe copy $BlobURI $dpdump --overwrite=ifsourcenewer --check-md5=FailIfDifferent"
  Write-Log -level INFO -message  "---------------------------"

  & F:\azCopy\AzCopy.exe copy $BlobURI $dpdump --overwrite=ifsourcenewer --check-md5=FailIfDifferent
} catch {
  Write-Log -level ERROR -message  "Error running script"
  Write-Log -level ERROR -message  $_.Message
  exit -1
}

已尝试的传参方式

以下几种传参写法均未解决参数为空的问题:

-Parameter @{ PDB = $PDB; BlobURI = $BlobURI }
-Parameter @{ "PDB" = $PDB; "BlobURI" = $BlobURI }
-Parameter @{ PDB = "$PDB"; BlobURI = "$BlobURI" }
-Parameter @{ "PDB" = "$PDB"; "BlobURI" = "$BlobURI" }
-Parameter $params

解决方案

1. 修复脚本路径的核心错误

你当前用Out-File -InputObject $ScriptPath -FilePath ScriptToRun.ps1的写法完全错误:这只是把VM上的脚本路径字符串写入了本地文件,而非脚本内容。Invoke-AzVMRunCommand的-ScriptPath参数要求传入Function App运行环境本地的脚本路径,而非VM上的路径,这是导致后续一系列问题的根源。

推荐两种正确的处理方式:

方式一:直接嵌入脚本内容

把VM上的脚本内容直接定义在Function App代码中,用-ScriptContent参数传递:

# 定义要在VM上执行的脚本内容
$scriptContent = @'
param(
  [string]$PDB,
  [string]$BlobURI
)

$logFile = "F:\azcopy\Info.txt"
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"
}

try
{
  $folder = switch ($PDB)
  {
    'QA' {'094D2AA1A909459BA36ABEEA7F7732F6'}
    'DEV' {'0B2305B6305547F389F96C800630CD21'}
  }

  $dpdump = "F:\app\oracle\admin\hs\dpdump\$folder"

  Write-Log -level INFO -message  "---------------------------"
  Write-Log -level INFO -message  "Copying:  $BlobURI"
  Write-Log -level INFO -message  "To folder $dpdump"
  Write-Log -level INFO -message  "---------------------------"
  Write-Log -level INFO -message  "F:\azCopy\AzCopy.exe copy $BlobURI $dpdump --overwrite=ifsourcenewer --check-md5=FailIfDifferent"
  Write-Log -level INFO -message  "---------------------------"

  & F:\azCopy\AzCopy.exe copy $BlobURI $dpdump --overwrite=ifsourcenewer --check-md5=FailIfDifferent
} catch {
  Write-Log -level ERROR -message  "Error running script"
  Write-Log -level ERROR -message  $_.Message
  exit -1
}
'@

# 调用Invoke-AzVMRunCommand
Invoke-AzVMRunCommand `
  -ResourceGroupName 'RESOURCE_GROUP' `
  -VMName 'VM_NAME' `
  -CommandId 'RunPowerShellScript' `
  -ScriptContent $scriptContent `
  -Parameter $params

方式二:从存储账户下载脚本到本地

若脚本内容较长,可将脚本上传至存储账户,在Function App中先下载到临时目录,再用-ScriptPath传递:

# 下载脚本到Function App临时目录
$localScriptPath = Join-Path $env:TEMP "CopyToDump.ps1"
Invoke-WebRequest -Uri "https://STORAGENAME.blob.core.windows.net/CONTAINER/CopyToDump.ps1$sasToken" -OutFile $localScriptPath

# 执行VM命令
Invoke-AzVMRunCommand `
  -ResourceGroupName 'RESOURCE_GROUP' `
  -VMName 'VM_NAME' `
  -CommandId 'RunPowerShellScript' `
  -ScriptPath $localScriptPath `
  -Parameter $params

# 清理临时文件
Remove-Item $localScriptPath

2. 验证参数来源的有效性

在Function App代码中添加日志,确认队列传递的参数是否存在:

Write-Host "QueueItem中的PDB值: $PDB"
Write-Host "生成的BlobURI: $BlobURI"

3. 确认VM脚本的参数接收

在VM脚本开头添加日志,直接输出接收的参数值,排查是否是脚本内部处理问题:

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

$logFile = "F:\azcopy\Info.txt"
Write-Log -level INFO -message "接收到的PDB参数: $PDB"
Write-Log -level INFO -message "接收到的BlobURI参数: $BlobURI"
# 后续原有代码...

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 19:39:24