AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 47534
Accepted
hasen
hasen
Asked: 2009-07-30 05:12:50 +0800 CST2009-07-30 05:12:50 +0800 CST 2009-07-30 05:12:50 +0800 CST

多个目录的原子复制

  • 772

这个问题是关于 Web 应用程序的部署。

简介(可以跳过)

我正在使用 django,而我的托管服务提供商设置 django 支持的方式最终导致 webapp 分散在至少三个位置:

  • 实际应用代码在/something/<my_apps>/
  • 网站设置/网址/模板/something/<my_site>/
  • css、javascript 和其他“媒体”在/something_else/media/

因此,当我部署/升级网站时,我需要一次更新多个目录。

实际问题:

有没有办法进行原子文件复制?无论如何,我都不是 linux 系统的“专家”,所以请原谅我的无知。

复制操作涉及几个目录树,两个或三个,基本上:

copy _tree1 to tree1
copy _tree2 to tree2

原子,我的意思是:

  • 它要么完全复制,要么根本没有复制。它永远不应该处于一些复制但失败的状态。
  • 它在尽可能短的时间内完成。理想情况下,系统不应该在某个时间点看到正在进行的副本,它要么看到文件的旧版本,要么看到新版本;它在任何时候都不会看到文件 A 的旧版本,而是文件 B 的新版本。如果这不完全可能,那么它应该不会超过几毫秒。

我的想法是有类似双缓冲的东西:我在一个暂存区准备好所有东西,例如,_tree_x然后将它复制移动到tree_x应该是一个原子操作,它只是改变磁盘上的指针。

我认为单个这样的复制移动操作在 linux 中是原子的(不是吗?),但我也需要几个这样的操作是原子的;我希望将它们视为单次移动操作。

linux deployment
  • 6 6 个回答
  • 2934 Views

6 个回答

  • Voted
  1. Best Answer
    Clinton Blackmore
    2009-07-30T05:22:56+08:002009-07-30T05:22:56+08:00

    我认为您在临时区域的正确轨道上。我不知道任何原子命令,但是如果您暂存文件,然后使用脚本删除第一个目录并移动(而不是复制)第二个目录,并对所有三个目录执行此操作,它应该非常快。

    或者,您可能想要使用符号链接。这样你可以大致:

    /version/22/<my-apps>
    /version/22/<my-site>
    /version/22/<my-media>
    

    并部署/version/23具有相同子目录的目录。然后,实际文件所在的位置(同样,为了速度,您需要一个脚本),您可以使用符号链接,这样当任何人访问最新页面时,他们都会获得最新版本(这一切都会发生)透明地,他们不知道)。这样做的好处是您的旧作品仍然存在,直到您决定删除它。[虽然,当然,版本控制系统更适合用于保留较旧的工作。]

    您必须检查 1)您可以运行脚本(并且以这种方式网络用户不能!),以及 2)您可以使用符号链接(因为某些网络服务器被配置为不遵循它们。)

    • 6
  2. Evan Anderson
    2009-07-30T05:19:41+08:002009-07-30T05:19:41+08:00

    也许我没有完全考虑到这一点,但为什么不将您的复制操作复制到一个新目录呢?完成后,将旧目录“mv”到另一个名称,并将新目录“mv”到所需名称。

    这在技术上不是原子的,因为有一段时间旧目录将被移动而新目录还没有到位,但这可能已经足够好了。

    • 2
  3. Michael Shaw
    2009-07-30T07:03:52+08:002009-07-30T07:03:52+08:00

    对于大型网站,可以通过让多个服务器处理请求来处理站点更新。然后,您可以使一台服务器脱机,对其进行更新,然后将其重新联机,对集群中的其他服务器重复此操作。

    对于单个托管站点,通过将站点关闭页面放入根文件夹中的 index.html 中,然后进行更改来关闭网站可能是有意义的。

    如果您确实需要尽可能多地保持网站正常运行,我可以建议以下内容:

    1. 不存在原子副本,但是,重命名单个文件夹确实会原子地发生。通过将重命名放入脚本并运行该脚本,您可以快速地一个接一个地进行一系列重命名。您将需要两倍于站点的磁盘空间才能在服务器上同时拥有 before 和 after 文件夹。

    2. 这并不能解决您的问题 - 只是减少了曝光。前后版本可能需要不同的数据库数据字段,因此 SQL 查询也需要运行。一个人可能在您进行更新的同时进行页面加载。网页加载的开始可以加载更改之前的页面,页面加载的最后部分可以使用复制之后的文件。

    • 0
  4. wfaulk
    2009-07-30T09:10:10+08:002009-07-30T09:10:10+08:00

    首先,最好的方法是更改​​您的 httpd 配置以指向新目录,然后重新启动 httpd。我认为这是不可能的。

    我有一个想法,假设您的三个目录中的数据不会一直在变化,因为它需要将这三个原始目录非原子移动到这些目录的副本。我不是 100% 确定这会起作用,但你可以测试它。对我来说,把它写成脚本比用英语解释更容易。让我知道是否需要进一步解释。

    假设三个标称路径是:/pathA/dir1、/pathA/dir2、/pathB/dir3

    mkdir /路径C
    ln -s 路径C /linkI
    cd /路径A
    tar pcf - dir1 | (cd /pathC; 焦油 pxf -)
    tar pcf - dir2 | (cd /pathC; 焦油 pxf -)
    cd /路径B
    tar pcf - dir3 | (cd /pathC; 焦油 pxf -)
    cd /路径A
    mv dir1 dir1.orig && ln -s /linkI/dir1 dir1
    mv dir2 dir2.orig && ln -s /linkI/dir2 dir2
    cd /路径B
    mv dir3 dir3.orig && ln -s /linkI/dir3 dir3
    mkdir /路径D
    cd /路径D
    mkdir 目录1
    mkdir 目录2
    mkdir 目录 3
    (cd dir1 &&)
    (cd dir2 &&)
    (cd dir3 &&)
    光盘 /
    ln -sf pathD /linkI

    (编辑:嗯,不知何故我错过了克林顿布莱克莫尔的上述回应,这与我的建议基本相同。所以没关系。)

    • 0
  5. ayke
    2014-02-27T14:03:00+08:002014-02-27T14:03:00+08:00

    对于那些阅读这个老问题的人来说,这是可能的,但它需要许多符号链接。

    我的答案基于 Clinton Blackmore 的答案(目前接受的答案)。

    不能以原子方式更改多个目录(或多个文件)。所以我们不能直接使用目录。可以使用 rename() 系统调用自动更新单个文件(用新文件替换旧文件)。符号链接可以以相同的方式更新,使用mv -T不mv取消对目标的引用。

    所以,如果我们有这些目录:

    /srv/dirA/
    /srv/dirB/
    /srv/dirC/
    

    我们可以使它们都成为其他三个目录的符号链接:

    /srv/dirA -> /version/current/dirA
    /srv/dirB -> /version/current/dirB
    /srv/dirC -> /version/current/dirC
    

    /version/current反过来,只是指向当前版本目录的符号链接:

    /version/current -> /version/22/
    

    然后可以使用两个简单的命令更新整个 Web 应用程序,其中最后一个命令一次“替换”所有三个目录(它实际上并不替换目录,它只是替换这些目录指向的位置):

    $ ln -s /version/23/ /version/next
    $ mv -T /version/next /version/current
    

    我还没有实际测试过这个,但它应该可以工作。该-T标志可以是非标准标志。作为替代方案,python -c "import os; os.rename('/version/next', '/version/current')"可以改为使用(也未经测试)。

    我不知道性能影响会是什么,但如果您已经在运行 Django,我怀疑它是否会很重要。我认为,如果您以尽可能低的延迟(如 CDN)提供大量静态文件,这可能很重要,即便如此,它可能只会对性能产生很小的影响。简而言之,您不必担心性能。

    请注意,有一些问题:Django 是一个服务器,不会同时重新启动。为了使其真正具有原子性,Django 必须以完全跳过“当前版本”概念的方式进行设置。相反,您将从当前版本启动 Django 以供生产使用。对于更新,将启动下一个版本,然后重新启动服务器(我假设大多数网络服务器都有某种方式可以在不脱机的情况下重新启动),并且整个过程应该是原子的。但我不是这方面的专家。

    另一个问题(正如 Ptolemy 所提到的)是,在繁忙的服务器上,由于缓存以及在页面加载期间在不同时间请求多个资源的事实,会有一些人看到部分来自一个版本和部分来自另一个版本的页面(资源加载之间可能有几秒钟)。我想到了这两个,缓存将是最重要的一个,但也是最容易解决的。不过,我怀疑这在实践中会成为一个很大的问题。

    • 0
  6. Raman
    2015-11-20T22:54:00+08:002015-11-20T22:54:00+08:00

    您是否尝试过使用atomic-rsync?它使用 rsync 和 mv 命令的组合,如其他答案中所建议的那样。

    • 0

相关问题

  • 多操作系统环境的首选电子邮件客户端

  • 你最喜欢的 Linux 发行版是什么?[关闭]

  • 更改 PHP 的默认配置设置?

  • 保护新的 Ubuntu 服务器 [关闭]

  • (软)Ubuntu 7.10 上的 RAID 6,我应该迁移到 8.10 吗?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    从 IP 地址解析主机名

    • 8 个回答
  • Marko Smith

    如何按大小对 du -h 输出进行排序

    • 30 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    Windows 中执行反向 DNS 查找的命令行实用程序是什么?

    • 14 个回答
  • Marko Smith

    如何检查 Windows 机器上的端口是否被阻塞?

    • 4 个回答
  • Marko Smith

    我应该打开哪个端口以允许远程桌面?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    MikeN 在 Nginx 中,如何在维护子域的同时将所有 http 请求重写为 https? 2009-09-22 06:04:43 +0800 CST
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    0x89 bash中的双方括号和单方括号有什么区别? 2009-08-10 13:11:51 +0800 CST
  • Martin Hope
    kch 如何更改我的私钥密码? 2009-08-06 21:37:57 +0800 CST
  • Martin Hope
    Kyle Brandt IPv4 子网如何工作? 2009-08-05 06:05:31 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve