我试图echo
在 Puppet 规则内部使用向 中添加一行.bashrc
,但我似乎无法正确引用。
'/usr/bin/echo -E PS1=\"[\t--------------------------------------------------------\n-\u@\h:\W]\$\" >> /home/unu/.bashrc'
这件事给了我以下结果:
PS1="[t--------------------------------------------------------n-u@h:W]$"
另一种尝试:
'/usr/bin/echo -E PS1="[\t--------------------------------------------------------\n-\u@\h:\W]\$" >> /home/unu/.bashrc'
这件事给了我以下内容:
PS1=[\t--------------------------------------------------------\n-\u@\h:\W]$
另一个:
'/usr/bin/echo -e PS1="[\\t--------------------------------------------------------\\n-\\u@\\h:\\W]\\$" >> /home/unu/.bashrc'
这个给了我这个:
PS1=[ --------------------------------------------------------
-\u@\h:\W]$
我似乎无法找到一种方法来做到这一点,而不需要\
以"
某种方式进行解释。我该怎么做?
我想过使用更多引号,但这会导致 Puppet 出现语法错误:
"/usr/bin/echo -e 'PS1="[\\t--------------------------------------------------------\\n-\\u@\\h:\\W]\\$"' >> /home/unu/.bashrc"
得到这样的结果:
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Syntax error at '' (file: /etc/puppetlabs/code/environments/production/modules/profile/manifests/ps1.pp, line: 3, column: 38) on node centoslave1
这是整个代码:
class profile::ps1 {
exec { 'myps1':
command => "/usr/bin/echo -e 'PS1="[\\t--------------------------------------------------------\\n-\\u@\\h:\\W]\\$"' >> /home/unu/.bashrc"
}
}
答案1
到底是怎么回事
命令=>“/usr/bin/echo -e 'PS1=”[\\t-------------------------------------------- --------------------------\\n-\\u@\\h:\\W]\\$"' >> /主页/unu/.bashrc"
了解哪里出了问题是纠正错误的线索。元素的右侧(位于 之后=>
)必须是字符串。字符串在 Puppet 中有多种形式。双引号字符串以双引号开头,以第二组结尾。所以你的字符串是
“/usr/bin/echo -e 'PS1=”然后,您可以在其后添加对于清单而言语法不正确的乱码:
[\t------------------------------------------------------------ ---------\n-\u@\h:\W]\$和另一个字符串:
“'>>/home/unu/.bashrc”
正确执行此操作
自下而上构建正确的设置。从您希望命令输出到该文件的内容开始。输出是一个 shell 命令,它将PS1
shell 变量设置为:
[\t------------------------------------------------------------ ---------\n-\u@\h:\W]\$这样的命令是,使用单引号(这里最好使用双引号,因为它不需要对那些
\
和$
字符进行转义)来阻止 shell 对转义序列进行转义:PS1='[\t-------------------------------------------------------- ------------\n-\u@\h:\W]\$'
echo
您可以通过 shell 调用来输出这样的命令(我们将返回到这一点),但是您需要通过更多转义来确保单引号到达echo
命令:echo PS1=\''[\t-------------------------------------------------------- ---------------\n-\u@\h:\W]\$'\'
然而,这存在问题,因为echo
跨平台和 shell 没有一致的行为,并且(讽刺的是)它的可能的转义序列的转换实际上是不是你想要什么。事实上,尽管您的问题上有标签,但运行命令的 shell 不一定是 Bourne Again shell,具体取决于操作系统(您尚未指定)。例如,它可能是 Debian Almquist shell。为了获得更好的结果,请使用printf
:
printf "PS1='%s'\n" '[\t------------------------------------ ---------------------\n-\u@\h:\W]\$' >> /home/unu/.bashrc
请注意,到目前为止的假设是它是提供给 shell 执行的命令行。对传递给echo
和的参数进行转义和引用printf
,以便它们最终得到正确的内容,这是根据 shell 规则进行的。因此,请注意有关提供商的问题评论。
现在你需要编码那在木偶弦中。单引号字符串在这里也是更好的选择,因为您只需要转义'
和\
字符(这与壳单引号字符串的规则,注意):
命令 => 'printf "PS1=\'%s\'\\n" \'[\\t---------------------------------------- ------------------------------\\n-\\u@\\h:\\W]\\$\ ' >> /home/unu/.bashrc'
进一步阅读
- ”语言:数据类型:字符串”。Puppet 4.9 参考手册。 puppet.com。
答案2
(至少)有两个层面的因素会吞噬你的角色:
- 贝壳
echo
本身
如果你运行:
echo "hello, \"world\""
你得到输出
hello, "world"
因为贝壳吃了反斜杠处的双引号,而不是 echo。 shell 将它们视为 shell 语法,表示将其hello, "world"
作为单个参数传递给 echo。然后打印回声,加上换行符。
echo -e
特别是还解释反斜杠序列(取决于实现);解决这个问题的简单方法是使用printf '%s\n' WHATEVER
代替echo WHATEVER
.
在大多数情况下,您可以使用单引号保护某些内容免受 shell 的影响(只要它本身不包含单引号)。所以,您可能想要:
printf '%s\n' 'PS1="[\t--------------------------------------------------------\n-\u@\h:\W]\$"'
这使:
PS1="[\t--------------------------------------------------------\n-\u@\h:\W]\$"
如果您必须在多层 shell 转义中幸存下来,您可能会发现printf '%q\n' WHATEVER
有用,它以一种在 shell 中幸存的格式打印它(但这可能是 Bash 独有的功能,尚未检查)。
顺便说一句:如果您需要保护单引号字符串中的单引号,则必须执行以下操作'\''
:
$ printf '%s\n' 'i'\''ll'
i'll
如果你仔细看的话,实际上是'i'
++ 。\'
'll'
PS:PS1
经历了另一次扩展(请参阅 Bash 文档);你显然知道这些\u
。但变量也会扩展——所以如果你在最后有一些东西$
,你需要转义它(用三如果在双引号字符串内则使用反斜杠):PS1="foo\\\$PATH % "
答案3
使用printf
:
printf '%s\n' 'PS1="[\t--------------------------------------------------------\n-\u@\h:\W]\$"' >> /home/unu/.bashrc
答案4
您可以简单地使用cat
:
cat /var/tmp/ps1-file >> /home/unu/.bashrc
可以手动创建(使用您喜欢的编辑器),这样您就可以避免//ps1-file
中的转义问题。为了使该文件到达节点,您需要添加bash
echo
printf
文件部分。
file { "/var/tmp/ps1-file"
source => 'puppet:///modules/bashrc/ps1'
}
这意味着将原始文件放在modulepath
.由于其内容是少量文本,您可以用 指定它们content =>
,但这会产生其自身的引用/转义问题。