GitHub Action工作流中PowerShell命令执行失败问题求助
PowerShell命令在GitHub Action工作流中执行失败的原因排查
问题场景
构建自定义GitHub Action时,执行以下PowerShell命令出现语法错误:
powershell -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$VerbosePreference = 'SilentlyContinue' ; Get-ChildItem -LiteralPath '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f $_.FullName) ; $_ } | Unblock-File | Out-Null"
报错信息:
At line:1 char:127 + ... h '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f .FullNa ... + ~ You must provide a value expression following the '-f' operator. At line:1 char:128 + ... | ForEach-Object { Write-Verbose ('Unblock: {0}' -f .FullName) ; } | ... + ~~~~~~~~~ Unexpected token '.FullName' in expression or statement. At line:1 char:127 + ... h '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f .FullNa ... + ~ Missing closing ')' in expression. At line:1 char:93 + ... inue' ; Get-ChildItem -LiteralPath '%~dp0' | ForEach-Object { Write-V ... + ~ Missing closing '}' in statement block or type definition. At line:1 char:137 + ... ForEach-Object { Write-Verbose ('Unblock: {0}' -f .FullName) ; } | ... + ~ Unexpected token ')' in expression or statement. At line:1 char:142 + ... ach-Object { Write-Verbose ('Unblock: {0}' -f .FullName) ; } | Unblo ... + ~ Unexpected token '}' in expression or statement. At line:1 char:144 + ... h-Object { Write-Verbose ('Unblock: {0}' -f .FullName) ; } | Unblock ... + ~ An empty pipe element is not allowed. + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : ExpectedValueExpression
原因分析
- YAML环境的
$符号解析问题:GitHub Action的YAML配置会自动解析$开头的变量,原命令中的$_和$VerbosePreference里的$被YAML解析器处理后丢失,导致PowerShell收到的命令中变成.FullName和VerbosePreference,直接引发语法错误。 - 路径变量语法不兼容:
%~dp0是CMD脚本的专用变量,用于获取当前脚本所在目录,但在GitHub Action直接调用PowerShell的场景下,这个变量无法被PowerShell识别,会被当作字面量路径处理,大概率找不到对应目录。
修复方案
方案1:转义$符号并替换路径变量
将命令中的所有$替换为$$(YAML中用于转义$的写法),同时把%~dp0替换为GitHub Action的内置变量${{ github.action_path }}(自定义Action的脚本目录)或$PWD.Path(当前工作目录):
powershell -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$$VerbosePreference = 'SilentlyContinue' ; Get-ChildItem -LiteralPath '${{ github.action_path }}' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f $$_.FullName) ; $$_ } | Unblock-File | Out-Null"
方案2:改用多行PowerShell脚本写法
在GitHub Action中直接指定shell: powershell,用多行脚本的方式避免引号和转义问题,可读性更强:
- name: Unblock Action Files shell: powershell run: | $VerbosePreference = 'SilentlyContinue' Get-ChildItem -LiteralPath "${{ github.action_path }}" | ForEach-Object { Write-Verbose ("Unblock: {0}" -f $_.FullName) $_ } | Unblock-File | Out-Null
内容的提问来源于stack exchange,提问作者Nesan Mano
相关产品推荐
相关产品推荐

