Capistrano 3在目录内执行命令

33

我正在尝试编写一个用于Capistrano 3的任务,其中包括在当前发布的目录中执行'composer install'。它看起来像这样:

namespace :composer do
  desc 'Install dependencies with Composer'
  task :install do
    on roles(:web) do
      within release_path do
        execute "#{fetch(:composer_command)} install"
      end
    end
  end
end

composer_command 在我特定的情况下设置在staging和production文件中 - 设置为 php /home/user/composer.phar

由于某种原因,该命令实际上并没有在当前发布目录中运行,而是在父目录中运行(包含current、shared、releases等目录)。

我进一步深入研究发现,当我运行单词命令时,例如:

within release_path do
    execute "pwd"
end

这个命令可以正常工作,并在当前发布目录下运行。但是... 当我运行一个带有空格的命令时,比如:

within release_path do
    execute "pwd && ls"
end

它在父目录中运行,而不是由within块设置的目录。

可以有人阐明一下吗?谢谢!

5个回答

34

闻起来像是Cap 3的一个bug。

我建议从shell的角度保证你在想要的位置。

execute "cd '#{release_path}'; #{fetch(:composer_command)} install"

4
我提出了一个问题 - https://github.com/capistrano/capistrano/issues/719结果发现这是SSHKit的限制。所以我会采用你的解决方案 - 就像旧版Capistrano 2一样。 - Rahul Sekhar
1
在文档中有解释(http://capistranorb.com/documentation/getting-started/tasks/)。请参考此答案(https://dev59.com/U2Ik5IYBdhLWcg3wPcCB#32499307)。 - x-yuri

11

您可以在保留自然字符串语法的同时,保留within()with()default_env等所有细节:

within release_path do
  execute *%w[ pip install -r requirements.txt ]
end

7

一些提示:

1)Capistrano在很多事情中使用SSHKit, 其中包括命令执行。为了简化使用Composer,您可以配置命令映射(在deploy.rbproduction.rb等文件中),以下是两个示例:

SSHKit.config.command_map[:composer] = "#{shared_path.join('composer.phar')}"
SSHKit.config.command_map[:composer] = '/usr/bin/env composer.phar'

下一步,您可以像这样执行它:
execute :composer, :install

2) 从安全角度考虑,禁用php设置中的allow_url_fopen是明智的,但不幸的是,Composer需要启用它才能正常运行。您可以使用以下方法将其全局禁用:

SSHKit.config.command_map[:composer] = "/usr/bin/env php -d allow_url_fopen=On #{shared_path.join('composer.phar')}"

查看iniscan,获得有关php设置的更多安全建议。

3)Composer有一个选项-d、--working-dir,你可以将其指向包含composer.json文件的目录,以便从任何其他目录运行Composer。这应该解决你的问题:

execute :composer, '-d', release_path, :install

4) 你可能想看一下 capistrano-composer 项目 :)


不知道是由于Capistrano的更新还是我的特定构建情况,但我必须稍微修改你的第二个示例: SSHKit.config.command_map[:composer] = "/[直接完整路径到]/composer.phar" 放在我的deploy.rb中。之后,在我的.rake文件中添加 execute :composer, "install" 就可以正常工作了。 - karolus

5

实际上,您对within函数的使用是几乎正确的。您已经把整个字符串作为命令传递给它了,但是文档指出这会导致不可靠的行为(我本人也有这种经历)。

execute的第一个参数成为一个符号而不是一个包含空格的字符串:

within release_path do
    execute fetch(:composer_command).to_sym, "install"
    execute :pwd
    execute :ls
end

4

仅供参考,这里有Capistrano文档解释为何within {}不能与带空格的参数一起使用。希望这可以帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接