寻找一种安全的方式来部署PHP代码

6

我们现在的做法

我们有一个文件服务器(使用NFS),多个Web服务器挂载并将这些挂载用作Web根目录。当我们部署代码库时,我们将归档文件(tar.gz)SCP到NFS服务器,并直接在文件服务器的“Web目录”中解压数据。

问题

在部署过程中,我们看到一些I/O错误,通常是当请求的文件无法读取时:Smarty error: unable to read resource: "header.tpl"。这些错误似乎在部署完成后消失,因此我们认为直接将数据解压到Web目录可能不太安全。我猜我们需要一些原子性的东西。

我的问题

如何能够将新文件原子地复制到现有目录(Web服务器的根目录)中?

编辑

我们正在向Web目录中不妥协的文件添加文件,而该目录中已经存在文件。因此,复制目录或使用符号链接不是选项(我所知道的)。


1
重命名是原子性的(mv),最好使用软链接,实际的网站目录只是一个指向/storage/www.revision.3282378的链接。 - jackdoe
5个回答

1

这是我的做法。

例如,DocumentRoot 是 /var/www/sites/www.example.com/public_html/:

cd /var/www/sites/www.example.com/
svn export http://svn/path/to/tags/1.2.3 1.2.3
ln -snf 1.2.3 public_html

您可以轻松地修改此内容,以在更改符号链接之前扩展您的.tar.gz,而不是从svn导出。重要的部分是更改符号链接的原子应用。


1
我认为使用rsyncscp更好,只有更改的文件才会被同步。但是通过脚本部署代码对于团队开发来说不太方便,而且部署中的错误不够人性化。
你可以考虑Capistrano、Magallanes、Deployer,但它们也是脚本。我可能会向你推荐尝试walle-web,这是一个用PHP编写并带有yii2框架的部署工具。我已经在我们公司托管了几个月,它在部署测试、模拟和生产环境时运行得非常顺畅。
它依赖于一组bash工具,包括rsync、git、link,但是Web用户界面一般都很适合操作,建议一试 :)

欢迎来到Stack Overflow!我注意到您在本站上的五个回答(包括最近删除的两个)都在推广同一个工具walle-web。请花点时间阅读我们的自我推广指南。重要的是,如果您与该工具有关联,您需要在每个答案中披露这一点。此外,您真的不应该在本站的所有答案中推广您的工具。 - josliber

0
为什么不在两个目录中分别放置两个不同版本的网站。这样,当您完成在site_2上部署后,只需在Web服务器配置(例如Apache)中切换站点目录,并将所有文件复制到site_1目录中。然后,您可以在site_1目录中部署并使用相同的方法从site_2切换到它。

我猜这里提到的方法是最快的。将你的新文件复制到一个临时文件夹中,然后重命名原始文件和新/临时文件夹(这不会花费太多时间)。 - djot
请看我的编辑-网站根目录中还有其他文件必须保留(营销网站),以及大量(>40GB)的用户生成内容,我不想一直复制它们... - mmattax

0

RSync 诞生的目的是为了运行... 呃... 我是说为了做这件事情

RSync 可以在本地文件系统和 ssh 上工作 - 它非常强大而且快速 - 只发送/复制已更改的文件。

它可以配置为删除已删除的任何文件(或仅从源中缺失的文件),也可以配置为保留它们。您可以设置排除列表,在同步时排除某些文件/目录。

这里有一个教程链接

关于原子性 - SO 上的另一个问题链接


说实话,我在过去的两年里已经在多个网站上使用了这个部署代码的方法,而且从未出现过任何错误(我会记录和发送错误信息邮件)——没有缺失文件的通知或错误提示——只需要一个简单的命令,就可以轻松地进行单一命令行脚本化部署。 - Tim G
这听起来是一个不错的选择,有没有在本地目录上运行它作为“一次性”操作的示例,或者rsync必须始终作为守护进程运行? - mmattax
我一直在本地运行rsync,作为打包Google Code项目的脚本的一部分。我很确定我从未配置过rsyncd - 我使用的是Mac。 - Tim G
1
我与所有的网络管理员交流后得知,他们亲眼见证了rsync在删除文件时摧毁整个文件系统的情况。而且,无论rsync有多快,如果您操作的不止一个文件,它都不是原子部署。 - ThorSummoner
1
使用带有删除标志的rsync在符号链接上操作是不安全的。 - ThorSummoner

0

我喜欢NFS的想法。我们将代码部署到挂载在前端的NFS服务器上。实际上,当我们想要发布新版本时,我们运行一个shell脚本。我们使用符号链接current指向最后一个发布目录,就像这样:

/fasmounts/website/current -> /fasmounts/website/releases/2013120301/

Apache的文档根目录是:

/fasmounts/website/current/public 

(事实上,Apache文档根目录是/var/www,它是指向/fasmounts/website/current/public的符号链接)

在所有内容正确上传之后,shell脚本会将当前的符号链接更新为新版本。


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