我希望远程运行一些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)并且不太了解红宝石,所以可能会有一些我错过的东西。
答案 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
方法调用。你可以在这里看到源代码:
你可以考虑通过在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进行编码,将其发送,然后在服务器端对其进行解码,以便对其进行完整的评估。这是有效的,但这是一个真正丑陋的黑客 - 我希望有人能提出更好的解决方案。