【问题标题】:Capistrano v3 not able to cleanup old releasesCapistrano v3 无法清理旧版本
【发布时间】:2013-11-02 00:11:08
【问题描述】:

由于我以 root 身份运行我的 rails 应用程序,它会在 tmp 目录中创建由 root 拥有的文件。因为这个

cap production deploy:cleanup

无法删除旧版本,因为它不是以 root 身份运行的。

我查看了 capistrano v3 代码,但没有看到以 root 身份运行清理命令的方法。是否缺少此选项或出现此问题是因为我在部署流程的另一个地方做错了什么。

我以 root 身份启动应用程序,因为我需要绑定到端口 80。

【问题讨论】:

    标签: capistrano


    【解决方案1】:

    我查看了 capistrano v3 代码,但没有看到以 root 身份运行清理命令的方法。是缺少此选项还是因为我在部署流程的另一个地方做错了什么而出现此问题。

    Capistrano 没有秘诀,我们依赖您正确设置部署用户的权限,如 http://www.capistranorb.com/ 中所述

    删除目录需要父目录的write权限,也就是说,给定以下目录结构:

    /var/www/releases/
                  \- 20131015180000
                  \- 20131015181500
                  \- 20131015183000
    

    您需要对/var/www/releases/ 目录的写入权限,因为该目录中的文件和目录列表存储在该目录中。

    来自similar StackSverflow question

    在 UNIX 和 Linux 中,删除文件的能力不取决于该文件的访问位。由文件所在目录的访问位决定。

    来自Wikipedia article on Unix File Permissions

    写权限授予修改文件的能力。当为目录设置时,此权限授予修改目录中条目的能力。这包括创建文件、删除文件和重命名文件。

    【讨论】:

    • 如果应用程序创建任何包含文件的文件夹,这将无法解决问题。然后发布目录下的文件夹将归root所有,因此部署用户将无法取消链接其内容。
    • 这可以通过在发布目录上设置setgid 来解决,并确保应用程序以umask 002 运行。 setgid 将确保将父目录的group 复制到其中创建的所有文件和目录。 umask 将确保新文件和文件夹的默认访问模式等同于ug+rw
    • 是的,这是 Coffee Bite 的回答,但 umask 很关键,而且这并不总是容易或安全的。在多线程服务器中,设置 umask 会干扰其他线程。 foob​​ar 的清理和 sudoer 修复更安全。
    • 我想看到 umask 在多线程情况下有害的引用,因为它指的是文件 creation,我看不到不同线程会最终不同的 umasks 竞相创建相同的文件。由具有正确 umask 的进程分叉的进程将继承它。如果我错了,我真诚地希望接受这方面的教育,因为我从未见过它在野外失败,我向所有使用 Capistrano 的人推荐它。 (我是维护者)
    • 如果应用程序创建的所有文件都使用相同的 umask,这不是问题。在不同的 umask 之间切换时会出现问题。至少在 PHP 领域(我知道最初的问题是关于 Rails),线程共享一个 umask,因此一个线程可以将其更改为另一个。
    【解决方案2】:

    您可能想做的一件事是在您的 linux 机器上创建一个名为 appweb 的组,并将 rootdeploy 用户添加到同一组中。然后,作为部署的一部分,chmodrelease_pathg+s 的权限将确保 root 用户创建的任何新文件都是组可写的。

    然后您应该能够以deploy 用户的身份删除旧文件夹。

    【讨论】:

    • 这仅在应用程序使用包含组写入位的 umask 创建其文件时才有效。 g+s 指定的 setgid 位将仅确保创建的文件属于新共享组,而不是该组可写。
    【解决方案3】:

    您还可以在清理旧版本之前触发任务:

    namespace :deploy do
    
      before :cleanup, :cleanup_permissions
    
      desc 'Set permissions on old releases before cleanup'
      task :cleanup_permissions do
        on release_roles :all do |host|
          releases = capture(:ls, '-x', releases_path).split
          if releases.count >= fetch(:keep_releases)
            info "Cleaning permissions on old releases"
            directories = (releases - releases.last(1))
            if directories.any?
              directories.each do |release|
                within releases_path.join(release) do
                    execute :sudo, :chown, '-R', 'deployuser', 'path/to/your/files/writtend/by/root'
                end
              end
            else
              info t(:no_old_releases, host: host.to_s, keep_releases: fetch(:keep_releases))
            end
          end
        end
      end
    
    end
    

    请注意,您需要授予部署用户执行此特定 sudo 命令的权限(使用 sudoers 定义文件。

    【讨论】:

    • 除非您有大量文件,否则很可能是微优化,但您可以立即rm 有问题的目录,而不是执行chmod。否则,:cleanup 运行一次,您将遍历目录结构两次。
    【解决方案4】:

    我遇到了类似的问题,因此,为了确认,通过 SSH 登录到我的 Web 服务器,并尝试了rm -rf [directory],由于相同的权限问题,它也失败了,甚至以管理员身份登录。不过,运行 chmod -R 755 [directory]/,然后运行 ​​rm -rf [directory]/ 确实有效。

    为了修复它,在项目的 silverstripe.rake 文件中,我更改了正在运行的命令: execute :chown, "-R [user]:[group] /path/to/project"

    到: execute :chmod, "-R 755 /path/to/project"

    到目前为止,在运行 cap [release name] deploy 时删除最旧版本没有更多问题

    【讨论】:

      猜你喜欢
      • 2011-01-08
      • 2013-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多