我有一个进程使用配置文件中的输入运行 powershell 命令。 (实际上它是 Windows 上的无人机 CI 执行器,带有无人机 YML 文件)。这个过程设置了一个环境变量,但我认为这个环境变量包含反引号,这些反引号被powershell解释为转义字符。
由于它是 OpenSSH key ,因此这会损坏 key 。有没有办法将环境变量的内容完全视为原始内容?无论是在设置还是读取期间(因为我不知道 key ,所以我不知道它发生在哪里)。
无人机 CI 配置:
- name: copy to archive on remote host
commands:
- Write-Output $env:SSH_KEY > ssh_key
- scp -i ssh_key file.zip user@host:/path/to/file.zip
- rm ssh_key
environment:
SSH_KEY:
from_secret: ssh_key
我知道这是一个功能键,因为它适用于我的 Linux 容器。但在 Windows 上,该格式被视为无效。
最佳答案
问题在于 >
的行为,即 redirection operator ,在 PowerShell 中,它实际上是 Out-File
的别名。 cmdlet:
字符编码:
在Windows PowerShell (
powershell.exe
) 中,它默认创建 UTF16-LE(“Unicode”)文件,大多数命令行实用程序都会这样做不认识。在 PowerShell (Core) 7+ (
pwsh
),幸运的是,它现在默认为无 BOM UTF-8,这现在是所有 cmdlet 以及 PowerShell 引擎本身在读取源代码方面的一致默认值。顺便说一句:在 Windows PowerShell 和 PowerShell (Core) 直至 v7.3.x 中,PowerShell 管道和
>
永远不会充当原始字节管道 用于中继来自外部程序的原始数据:此类数据总是首先解码为 .NET 字符串,其中>
/Out -File
然后根据默认编码写入文件。请参阅this answer作为背景。
尾随换行符:
- 在这两个版本中,默认情况下,在写入文件时会将平台原生的换行符附加到输入(每个输入对象),可以使用
-NoNewLine
来抑制> 切换。
- 在这两个版本中,默认情况下,在写入文件时会将平台原生的换行符附加到输入(每个输入对象),可以使用
最简单的解决方案是使用 New-Item
相反,令人惊讶的是,即使在 Windows PowerShell 中,它也会创建无 BOM 的 UTF-8 文件,并且从不附加尾随换行符(隐含 -ItemType File
):[1]
$env:SSH_KEY | New-Item -Force ssh_key
注意:
-
需要
-Force
来确保覆盖该名称的预先存在的文件。但是,-Force
还会根据需要创建一个不存在的目标目录,>
/Out-File
获胜不这样做。在 Windows PowerShell 中,使用
Out-File
(或Set-Content
,通常更适合纯文本输入)[2] 和-Encoding Utf8
不是一个选项,因为生成的文件总是使用 BOM 创建。鉴于 PowerShell(核心)7+ 默认为无 BOM UTF-8,您也可以使用:
$env:SSH_KEY | Set-Content -NoNewLine ssh_key
- 假设输入字符串仅包含 ASCII 范围字符,这也适用于 Windows PowerShell,因为
Set-Content
默认为ANSI 代码页,由旧系统区域设置确定,它是 ASCII 的超集。[3]
- 假设输入字符串仅包含 ASCII 范围字符,这也适用于 Windows PowerShell,因为
[1] 严格来说,这只适用于 PowerShell 的 current location是由 file-system provider 支持的- 然而,实际上几乎总是如此。如果不是,但您仍想创建一个文件,请指定完整文件系统路径,或者在相对路径前添加 FileSystem::
以定位文件系统提供程序的当前目录。
[2] 请参阅 this answer作为背景。
[3] 不幸的是,这意味着在 Windows PowerShell 中,不同的 cmdlet 具有不同的默认编码 - 请参阅 this answer 的底部部分为背景。
关于powershell忽略来自不同进程的输出的字符转义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77282612/