如何防止capistrano取代换行?

时间:2014-08-07 15:36:32

标签: ruby capistrano heredoc capistrano3

我希望远程运行一些shell脚本作为我的capistrano设置的一部分。为了测试该功能,我使用以下代码:

execute <<SHELL
cat <<TEST
something
TEST
SHELL

然而,这实际上是在运行/usr/bin/env cat <<TEST; something; TEST,这显然不会起作用。我如何告诉capistrano执行heredoc,而不是将换行符转换为分号?

我有Capistrano版本:3.2.1(耙子版本:10.3.2)并且不太了解红宝石,所以可能会有一些我错过的东西。

3 个答案:

答案 0 :(得分:3)

认为它可能只是将cat的参数指定为execute的第二个参数:

cat_args = <<SHELL
<<TEST
something
TEST
SHELL

execute "cat", cat_args

从@DavidGrayson发布的代码中,看起来只有命令(execute的第一个参数)才被清理。

我同意David的看法,更简单的方法可能是将数据放在一个文件中,what the SSHKit documentation suggests

  

从流上传文件

on hosts do |host|
  file = File.open('/config/database.yml')
  io   = StringIO.new(....)
  upload! file, '/opt/my_project/shared/database.yml'
  upload! io,   '/opt/my_project/shared/io.io.io'
end
     

IO流式传输对于上传内容非常有用,而不是“猫”,例如

on hosts do |host|
  contents = StringIO.new('ALL ALL = (ALL) NOPASSWD: ALL')
  upload! contents, '/etc/sudoers.d/yolo'
end
     

这使得人们不必为“echo(:cat, '...?...', '> /etc/sudoers.d/yolo')”之类的东西找出正确的转义序列。

这似乎对你的用例非常有用。

答案 1 :(得分:0)

负责此清理的代码可以在SSHKit::Command#sanitize_command!中找到,该类由该类的initialize方法调用。你可以在这里看到源代码:

https://github.com/capistrano/sshkit/blob/9ac8298c6a62582455b1b55b5e742fd9e948cefe/lib/sshkit/command.rb#L216-226

你可以考虑通过在Rakefile的顶部添加这样的东西来monkeypatching它什么都不做:

SSHKit::Command  # force the class to load so we can re-open it
class SSHKit::Command
  def sanitize_command!
    return if some_condition
    super
  end
end

这有风险,可能会在其他地方引入问题;例如,Capistrano可能有部分假设该命令没有换行符。

最好制作一个包含heredoc的shell脚本或将heredoc放在某个文件中。

答案 2 :(得分:0)

好的,所以这是我自己想出的解决方案,以防它对其他人有用:

str = %x(
base64 <<TEST
some
thing
TEST
).delete("\n")
execute "echo #{str} | base64 -d | cat -"

正如您所看到的,我对base64进行编码,将其发送,然后在服务器端对其进行解码,以便对其进行完整的评估。这是有效的,但这是一个真正丑陋的黑客 - 我希望有人能提出更好的解决方案。