Jenkins powershell脚本中的转义空间和解析变量不起作用

Posted

技术标签:

【中文标题】Jenkins powershell脚本中的转义空间和解析变量不起作用【英文标题】:Escape space and resolve variable in Jenkins powershell script not working 【发布时间】:2019-01-07 20:07:42 【问题描述】:

我尝试了不同的方法来逃避“程序文件”中的空间,但这不起作用。这部分执行后,我在 Jenkins 中收到以下错误:

powershell.exe : FileStream 被要求打开一个不是文件的设备。如需对“com1:”或“lpt1:”等设备的支持,请致电 At C:\web\JenkinsMaster\workspace\XXX@tmp\durable-d3011838\powershellWrapper.ps1:5 字符:3 + & powershell -NoProfile -NonInteractive -ExecutionPolicy 绕过 -Fi ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (FileStream was ... 'lpt1:', call :String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError CreateFile,然后使用将操作系统句柄作为 IntPtr 的 FileStream 构造函数。

CategoryInfo : OpenError: (:) [Out-File], NotSupportedException

FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand

PSComputerName : XXXXX

powershell script: '''
$pass = ConvertTo-SecureString -AsPlainText "XXXX" -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList "XXXX",$pass
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$session = New-PSSession -ComputerName XXXXXXXX -UseSSL -Credential $cred -SessionOption $sessionOption
Copy-Item $env:WORKSPACE\\* -Destination "C:\\data\\install\\" -Filter *TEST* -Recurse -Force -Verbose -ToSession $session
$filename = $env:JOB_NAME + "_" + $env:BUILD_DISPLAY_NAME + "_wwwroot.7z"
Invoke-Command -Session $session -ScriptBlock cmd /c "C:\\Program Files\\7-Zip\\7z.exe\\" x C:\\Data\\Install\\$filename -oC:\\data\\install\\test -aoa >NUL
Remove-PSSession $session
Exit-PSSession
'''

如果我将 Invoke-Command 更改为以下内容,则 Program Files 目录似乎已正确解析,但变量 $filename 不再解析。

Invoke-Command -Session $session -ScriptBlock cmd /c \'"C:\\Program Files\\7-Zip\\7z.exe" x C:\\Data\\Install\\$filename -oC:\\data\\install\\test -aoa >NUL'

powershell.exe : NotSpecified: (:String) [], RemoteException At C:\web\Jenkins\workspace\XXX@tmp\durable-53dbead2\powershellWrapper.ps1:5 字符:3 + & powershell -NoProfile -NonInteractive -ExecutionPolicy 绕过 -Fi ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (NotSpecified: (...RemoteException:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError

CategoryInfo : NotSpecified: (:String) [], RemoteException FullyQualifiedErrorId : NativeCommandError PSComputerName : XXXXX

错误:系统找不到指定的文件。

C:\Data\Install\$文件名

系统错误:

系统找不到指定的文件。

希望您能在这种情况下帮助我!其余命令运行正常。

谢谢!

【问题讨论】:

【参考方案1】:

我想知道是否有必要为此调用CMD shell。 我想直接调用带有参数的7z.exe 会更简单。

不过,您可以像这样构建自己的脚本块:

[ScriptBlock]::Create('cmd /c "C:\\Program Files\\7-Zip\\7z.exe" x C:\\Data\\Install\\' + $filename + ' -oC:\\data\\install\\test -aoa >NUL')

【讨论】:

【参考方案2】:

您的第一个命令中的7z.exe 路径有一个多余的尾随\,这会导致问题:

cmd /c "C:\\Program Files\\7-Zip\\7z.exe\\"  # <- trailing \\ shouldn't be there

在您的第二个命令中,您在传递给cmd /c ('...') 的命令周围使用引号,但'...' 字符串的内容在 PowerShell 中被视为文字,这就解释了为什么$fileName 没有展开(插值); 只有双引号 ("...") 字符串,并且在限制范围内,未加引号的命令参数在 PowerShell 中展开;例如,将Write-Output '$HOME' 的输出与Write-Output "$HOME" / Write-Output $HOME 的输出进行比较。

正如 iRon 所提到的,根本不需要涉及cmd - PowerShell 完全能够直接执行命令行程序,所以这应该可以工作:

Invoke-Command -Session $session -ScriptBlock  & "C:\\Program Files\\7-Zip\\7z.exe" x C:\\Data\\Install\\$using:filename -oC:\\data\\install\\test -aoa >$null 

由于直接调用7z.exe,现在不需要外引用,$fileName应该被扩展。

但是请注意,$fileName 已替换为 $using:fileName,这是为了让目标会话了解 本地 $fileName 变量所必需的- 见Get-Help about_Remote_Variables

由于7z.exe 文件路径被引用(由于包含空格,必须使用&amp;,呼叫操作员,调用它。

由于 &gt; 重定向现在由 PowerShell 自己执行,cmd 样式的 &gt;NUL 输出抑制已替换为其 PowerShell 模拟 &gt;$null。。 p>

【讨论】:

以上是关于Jenkins powershell脚本中的转义空间和解析变量不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何在我的 Powershell 脚本中使用 Jenkins 变量

通过 npm 脚本从 Powershell 使用 --collectCoverageFrom 运行 Jest 测试时,转义引号和斜杠的正确方法是啥?

如何从PowerShell命令行转义管道字符以传递到非PowerShell命令

更改 csv 文件中的日期时间格式 - 批处理脚本/Powershell [关闭]

持续集成~Jenkins里的powershell插件发布远程站点了

(20)Powershell中的特殊运算符