根据我的经验,我们在网络开发过程中遇到的一个更大的问题是在不同的服务器上保持不同的设置更新和安全。
我的公司拥有自己的CMS,目前已在100多台服务器上安装。目前,我们使用基于FTP的黑客方法,结合特定位置的升级脚本来升级所有CMS设置。当涉及多个自定义模块时,有效地管理这些设置变得越来越困难和风险。
一些上下文信息:我们主要在LAMP堆栈上开发。帮助我们销售CMS的主要因素之一是我们可以插入客户想要的任何东西。这可以是10到10,000行的自定义代码。
很多自定义工作都包含很少的代码;在Subversion中管理所有这些小部分代码对我来说似乎相当繁琐和低效(因为我们每周提供大约2个网站,这将导致很多分支)。
如果我有一些东西可以忽略,我很乐意听到你的声音。
提前致谢。
综述:首先,感谢您的所有答案。所有这些都非常有用。
我很可能会使用基于SVN的方法,这使得benlumley的解决方案最接近我将使用的方法。由于这个问题的答案在其他用例中可能有所不同,我会在运行结束时接受最多投票的答案。
请检查答案并投票选出您认为最具附加价值的答案。
答案 0 :(得分:8)
我认为使用版本控制系统并“分支”您必须修改的代码部分可能会成为鲁棒性和效率方面的最佳方法。
分布式版本系统可能最适合您的需求,因为它允许您在不同的“分支”上无缝更新“核心”功能,同时在需要时保留本地更改。
编辑:我非常确定使用分布式版本系统保持最新状态远不如您期望的那样乏味:您可以保留更改,确定您“它永远不会需要本地其他地方,而分布式方面意味着您部署的每个应用程序实际上都独立于其他应用程序,并且只传播您要传播的修复程序。”
答案 1 :(得分:6)
如果自定义您的应用程序涉及更改许多小代码,这可能表明您的应用程序的设计存在缺陷。您的应用程序应该有一组稳定的核心代码,可插入自定义库的扩展点,使用模板更改外观的功能,以及使用配置文件更改行为和安装插件的功能。这样,每个客户端都不需要单独的SVN分支。而是将核心代码和扩展插件库保持在源代码控制中。在另一个存储库中,为每个客户端创建一个文件夹,并将所有模板和配置文件保存在那里。
目前,创建SVN分支可能是唯一可以帮助您保持理智的解决方案。在您当前的状态下,您几乎不可避免地会犯错误并弄乱客户的网站。至少对于分支机构,您可以保证为每个客户端提供稳定的代码库。 SVN分支的唯一问题是,如果您在分支中移动或重命名文件,则无法将该更改合并回主干(您必须手动执行此操作)。
祝你好运!编辑:有关使用上述所有原则的精心设计的应用程序的示例,请参阅Magento E-Commerce。 Magento是迄今为止我使用过的功能最强大,可扩展且易于定制的Web应用程序。
答案 2 :(得分:4)
我可能错了,但在我看来,Aron之后是不是版本控制。版本控制很棒,我确信它们已经在使用它,但是为了管理数百个自定义安装的更新,你需要其他东西。
我正在思考一些专用软件包系统。您希望模块的每个版本都能跟踪其各自的依赖关系和“保证兼容性”,并使用此信息自动更新“安全”模块。
E.g。假设您已经构建了“Wiki”模块的新版本3。您希望将新版本传播到运行应用程序的所有服务器,但是您从版本2开始对Wiki模块中的一个接口进行了更改。现在,对于所有默认安装,这没有问题,但它会破坏在旧界面上安装自定义扩展。精心策划的包装系统可以解决这个问题。
要解决安全问题,您应该考虑在补丁上使用数字签名。有许多好的库可用于基于公钥的签名,所以只需使用看似所选平台的标准。
答案 3 :(得分:4)
不确定某人是否这么说,这里有很多长篇回复,而且我没有全部阅读过。
我认为更好的版本控制方法是让您的CMS独立存放在自己的存储库中,每个项目都独立存在。 (或者,所有这些可能是一个回购中的子文件夹我猜)
然后,您可以在需要它的每个项目中将其主干(或特定分支/标记,如果您愿意)用作svn:external。这样,您对CMS所做的任何更新都可以提交回其存储库,并且当它们被更新时(或者外部是svn:switch'ed)将被提取到其他项目中。
作为简化此操作的一部分,您需要确保CMS和自定义功能位于不同的文件夹中,以便svn externals正常工作。
IE:
project
project/cms <-- cms here, via svn external
project/lib <-- custom bits here
project/www <-- folder to point apache/iis at
(如果需要,你可以在www文件夹下有cms和lib)
这将允许您根据需要分支/标记每个项目。您还可以在每个分支/标记的基础上切换svn:external位置。
就实时更改而言,我建议您立即摆脱ftp并使用rsync或svn checkout / exports。两者都运作良好,选择取决于你。
我对rsync路由有很多经验,将svn导出到服务器。如果你沿着这条路走下去,写下一些shell脚本,你可以使用-n标志创建一个测试shell脚本来显示它将上传的文件而不上传它们。我通常为每个环境使用一对脚本 - 一个是测试,另一个是实际的。
共享密钥身份验证,因此您不需要密码来发送上传也可能很有用,具体取决于授予访问权限的服务器的安全性。
您还可以维护另一个用于进行批量升级的shell脚本,只需为要升级的每个项目调用相关的shell脚本。
答案 4 :(得分:2)
基本上,有一个“sites”文件夹,其中包含您要托管的每个站点的目录。每个文件夹中都有一个单独的settings.php,它允许您指定不同的数据库。最后,您可以(可选)在网站中拥有“主题”和“模块”文件夹。
这允许您对特定模块进行特定于站点的自定义,并将某些模块限制为这些站点。因此,您最终得到的网站绝大多数都完全相同,只有差异重复。将其与处理升级和更新的方式相结合,您可能拥有可行的模型。
答案 5 :(得分:2)
在代码中构建自我更新过程 它将检查更新并在为客户端配置它时/在何处/如何操作它们。
您必须创建某种模块列表(自定义或不自定义),这些模块需要在推出之前使用新版本进行测试。部署更新时,您必须确保正确测试和集成这些更新。希望你的设计可以解决这个问题。
理想情况下,更新是一些关键步骤。
a)备份,以便您可以退出。您应该可以退出 任何时候的整个更新。所以, 这意味着创建一个本地存档 的应用程序和数据库 第一
b)更新监控流程 - 让CMS系统电话回家寻找新版本。
c)安排可用性更新 - 您可能不希望更新在可用的第二次运行时运行。这意味着您必须创建某种类型的cron / agent才能在半夜自动进行系统更新。您还可以考虑在周末或特定日期更新客户端要求。您也可以错开推出更新,这样您就不会在1天内更新1000个客户端并获得技术支持。交错推出某种形式可能对你有利。
d)添加维护模式以更新网站 - 将网站踢入维护模式。
e) SVN签出或可下载软件包 - 理想情况下,您可以通过svn checkout进行部署,如果没有,则设置服务器以将svn生成的软件包提供到可以部署在客户端站点上的存档中。
f)部署数据库脚本 - 备份数据库,更新数据库,填充数据库
g)更新网站代码 - 所有这些工作只需一步。
h)对其运行一些测试。如果您的代码内置自检,那将是理想的。
答案 6 :(得分:2)
这就是我做的......
这可确保代码尽可能使用共享文件,但如果由于某种原因需要覆盖特定的类或文件,我可以在其文件夹中编写客户端特定的版本。
我的虚拟主机配置将包含类似
的行Alias /common <path>/shared/current_version/public_html/common
允许跨项目共享通用UI元素,图标等
在每个站点发布后,我通过创建一个分支来标记公共代码,以有效地冻结该时间点。这允许我将/ shared / version_xyz /部署到实时服务器。然后,我可以让虚拟主机使用特定版本的公共文件,或者如果我希望它获取最新更新,则将其指向current_version。
答案 7 :(得分:1)
您是否查看了Puppet(用于系统管理,包括应用程序部署)或Capistrano(在RubyOnRails中部署应用程序,但不仅限于这些)等工具?
答案 8 :(得分:1)
一种选择是设置只读版本控制系统(Subversion)。您可以将对存储库的访问权限集成到CMS中,并通过菜单调用更新,或者如果您不希望用户选择有关更新(可能是关键的),则会自动进行更新。使用版本控制系统还可以让您轻松保留不同的分支
答案 9 :(得分:1)
正如人们已经提到过使用版本控制(由于功能而我更喜欢Subversion)和分支将是最好的选择。 sourceforge上另一个名为cruisecontrol的开源软件。令人惊讶的是,你使用subversion配置了巡航控制,以及任何代码修改或serversion中添加的新代码,Cruise控件将自动知道并将为你构建。它会节省你的时间。
我在公司里做过同样的事情。我们有四个项目,必须在不同的服务器上部署该项目。我已经设置了cruiseconrol,这样代码库中的任何修改都会触发自动构建。另一个脚本将在服务器上部署该构建。你很高兴。
答案 10 :(得分:1)
如果您使用LAMP堆栈,我肯定会将解决方案文件转换为您的发行版的包,并将其用于传播更改。我推荐Redhat / Fedora因为RPM而且这是我的经验。无论如何,你也可以使用任何基于Debian的发行版。
前段时间我为管理ISP托管服务器制作了LAMP解决方案。他们有多台服务器来处理网络托管,我需要一种方法来部署我的经理的变更,因为每台机器都是独立的并且有一个在线经理。我制作了一个RPM包,其中包含解决方案文件(主要是php)和一些使用RPM运行的部署脚本。
对于自动更新,我们在yum.conf中的每个服务器上都设置了自己的RPM存储库。我设置了一个crontab作业,每天使用该可信存储库中的最新RPM更新服务器。
可以实现信任,因为您可以在RPM软件包中使用信任设置,例如使用公钥文件对其进行签名并仅接受已签名的软件包。
答案 11 :(得分:1)
Hm是否可以添加配置文件?你写道,很多小脚本正在做点什么。现在,如果你将它们构建到源代码中并用配置文件引导它们不应该“缓解”那个吗?
另一方面,为每个客户设立分支机构对我来说似乎是指数增长。你将如何“知道”你做了哪些事情,并且不要忘记在所有其他分支中“改变”。这看起来很难看。
似乎修订控件,配置选项和/或部署收据的组合似乎是一个“好”的想法......
答案 12 :(得分:1)
由于您的核心软件有很多变化,我认为您真的需要一个版本控制系统来保持从主干到各个客户端站点的更新。
所以,如果你认为Subversion会很乏味,那么你对于痛点将会有一个很好的理解......就个人而言,我不会推荐Subversion,因为它在管理和管理方面并不是那么好。跟踪分支机构尽管benlumley建议将核外软件用于外部设备是一个很好的建议,但如果您需要调整客户端站点的核心代码,则会出现故障。
查看Git的版本控制,它是为分支而构建的,而且速度很快。
查看Capistrano以管理您的部署。它是一个ruby脚本,通常与Rails一起使用,但它可以用于远程服务器上的各种文件管理,甚至是非ruby站点。它可以通过各种策略将内容传送到远程端,包括ftp,scp,rsync,以及从存储库中自动检出最新版本。它提供的好功能包括部署过程每一步的回调挂钩(例如,您可以复制可能不在版本控制中的特定于站点的配置文件),以及通过符号链接完成的发布日志系统 - 所以你如果遇到问题,可以快速回滚到之前的版本。
我建议使用包含分支列表及其托管位置的配置文件,然后使用脚本依次检查每个分支并上传最新更改。这可以通过cron'd自动进行夜间更新。