我正试图从官方文档中安装Operator Lifecycle Manager(OLM),这是一种帮助管理集群上运行的Operators的工具,但我一直收到下面的错误。可能出了什么问题?
这是命令的结果:
curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.22.0/install.sh | bash -s v0.22.0
/bin/bash: line 2: $'r': command not found
/bin/bash: line 3: $'r': command not found
/bin/bash: line 5: $'r': command not found
: invalid option6: set: -
set: usage: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...]
/bin/bash: line 7: $'r': command not found
/bin/bash: line 9: $'r': command not found
/bin/bash: line 60: syntax error: unexpected end of file
我已经尝试删除现有的curl,并下载并安装了另一个版本,但问题仍然存在。大多数在线解决方案都是为Linux用户提供的,它们都会导致Windows路径设置和文件问题。
我还没有找到一个解决使用curl
安装文件的问题。
我很乐意接受任何帮助。
在Windows上使用PowerShell时,当PowerShell将curl.exe
发出的stdout行传递给bash
时,必须明确确保它们与Unix格式的CRLF换行符n
和分隔,因为bash
和其他Unix shell一样,无法识别Windows格式的CRLFnewlinesrn
:
避免问题的最简单方法是通过cmd /c
调用:
cmd /c 'curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.22.0/install.sh | bash -s v0.22.0'
与PowerShell(见下文)不同,cmd.exe
的管道(|
)(以及其重定向运算符>
)充当原始字节管道,因此它只是将curl.exe
输出的任何字节流式传输到接收bash
调用,而不做更改。
修复PowerShell侧的问题需要更多的工作,并且天生就较慢:
(
(
curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.22.0/install.sh
) -join "`n"
) + "`n" | bash -s v0.22.0
注意:`n
是一个PowerShell转义序列,它生成一个文本LF字符,类似于某些bash
上下文中的n
注:
需要注意的是,从PowerShell 7.2.x开始,不支持通过管道传递原始字节:外部程序stdout输出在读取时总是被解码为.NET字符串,并且当将写入(其他)外部程序时,基于
$OutputEncoding
首选变量重新编码。- 有关更多信息,请参阅此答案,以及GitHub 1908号问题,了解未来对外部程序之间的原始字节流和重定向到文件的潜在支持
也就是说,PowerShell总是将来自外部程序(如
请注意,这些行(字符串)本身没有换行符;也就是说,关于最初将行分隔开的特定换行序列的信息在该点上丢失了(PowerShell本身可互换地识别CRLF和LF换行)curl.exe
)的输出解释为文本,并通过管道逐行发送,作为.NET字符串对象(PowerShell管道通常执行(.NET)对象)。
但是,如果接收命令是也是外部程序,则PowerShell会在每行中添加一个尾随平台本机换行符,在Windows上是CRLF换行符-这就是问题的原因。
通过使用(...)
在前面收集阵列中的行,可以使用-join
运算符将它们作为单个LF分隔的多行字符串发送,如上所示。
请注意,PowerShell也会将一个尾随的平台本机换行符附加到这个单行多行字符串中,但
bash
实际上会忽略输入的最末尾处的杂散rn
,假设最后一个真正的输入行以n
结尾,这就是表达式末尾额外的+ "`n"
所确保的。然而,在某些情况下,这个尾随的CRLF换行符确实会导致问题——请参阅此答案,以获取通过平台本机shell的示例和解决方案。
首先,我需要清楚一些事情:
- 根据问题的标签,我看到我们在PowerShell中,而不是linux/unix,甚至是Windows cmd shell
- 尽管如此,我们使用的是Unix
curl
(可能是curl.exe
),而不是Invoke-WebRequest
的PowerShell别名。我们之所以知道这一点,是因为-sL
的论点。如果Powershell使用别名,我们会看到完全不同的错误
接下来,我需要简要谈谈行尾。Windows默认情况下使用两个字符的LF/CR对(nr
)作为行尾,而不是Unix/linux中和bash所期望的单个LF(n
)字符。
有了这些背景,我现在可以解释问题的原因了。这是一个单管字符:
|
这是PowerShell管道,而不是Unix管道,因此该操作将curl
程序的输出放在PowerShell管道中,以便将其发送到bash
解释器。每一行都是管道上的一个单独项目,因此不再包括任何原始换行符。PowerShell管道将";正确的";这是在使用系统的默认行结尾调用bash之前,在本例中是Windows使用的LF/CR对。现在,当bash试图解释输入时,它在每行后面都会看到一个额外的r
字符,不知道该怎么处理
关键是,我们在Powershell中可能会做的去除多余字符的大部分操作,在完成后仍将通过另一个管道发送。我想我们可以告诉curl在不使用管道的情况下将文件写入磁盘,然后告诉bash运行保存的文件,但这很尴尬,需要额外的工作,而且速度要慢得多。
但我们可以做得更好。PowerShell默认情况下将curl返回的每一行视为管道上的一个单独项目。我们可以";技巧";而是使用CCD_ 33操作将一个大项目放在流水线上。这将为我们提供一个可以作为单个元素在管道上运行的大字符串。它最终仍然会有一个额外的r
字符,但当bash看到它时,脚本已经完成了它的工作。
实现这一点的代码可以在另一个答案中找到,他们应该为解决方案获得所有赞誉。我写这篇文章的目的是更好地解释发生了什么:为什么我们有问题,为什么解决方案有效,因为我必须通读几遍才能真正得到答案。