【问题标题】:What's the best practice for handling system-specific information under version control?在版本控制下处理系统特定信息的最佳实践是什么?
【发布时间】:2009-01-07 05:46:13
【问题描述】:

我是版本控制的新手,所以如果有一个众所周知的解决方案,我深表歉意。特别是对于这个问题,我正在使用 git,但我很好奇如何为所有版本控制系统处理这个问题。

我正在开发服务器上开发 Web 应用程序。我在两个地方定义了 Web 应用程序(不是文档根目录)的绝对路径名。在生产服务器上,这条路径是不同的。我很困惑如何处理这个问题。

我可以:

  1. 重新配置开发服务器以与生产服务器共享相同的路径
  2. 每次更新产品时编辑这两个匹配项。

我不喜欢 #1,因为我宁愿让应用程序灵活应对未来的任何变化。我不喜欢 #2,因为如果我开始在具有第三条路径的第二个开发服务器上进行开发,我将不得不在每次提交和更新时更改它。

处理此问题的最佳方法是什么?我想到了:

  1. 使用自定义关键字和变量扩展(例如在版本控制属性中设置属性 $PATH$ 并使其在所有文件中扩展)。 Git 不支持这一点,因为这会对性能造成巨大影响。

  2. 使用更新后和预提交挂钩。可能是 git 的可能解决方案,但每次我查看状态时,它都会报告这两个文件正在更改。不是很干净。

  3. 从版本控制之外的配置文件中提取路径。然后我必须将配置文件放在所有服务器上的相同位置。还不如从相同的路径开始。

有没有简单的方法来解决这个问题?我是不是想多了?

【问题讨论】:

    标签: git version-control configuration-files


    【解决方案1】:

    永远不要对文件系统路径等配置数据进行硬编码,并强制多个部署匹配。那是黑暗的一面,那里有很多痛苦。

    我发现构建我的系统以轻松支持多种配置非常有用且容易,我经常将配置文件并排提交到源代码管理中,但是生产的文件被混淆了(没有真正的密码)并且开发的文件是模板化的(所以checkout 不能覆盖开发人员的配置)。代码始终以与配置无关的方式打包——相同的二进制文件可以部署在任何地方。

    不幸的是,大多数语言/开发平台都不容易支持这一点(与 Ruby on Rails 不同)。因此,您必须在不同程度上自己构建它。

    一般来说,基本原则是在您的配置中加入间接性:在您的代码中指定的不是配置,而是如何找到配置。并且通常会调用几种间接方式:特定于用户的、特定于应用程序的、特定于机器的、特定于环境的。每个都应该以明确定义的位置/方式找到,并且它们之间应该有一个非常明确的优先级(通常是用户优先于机器优先于应用程序优先于环境)。您通常会发现每个可配置设置在一个位置都有一个自然归宿,但不要将该依赖项硬编码到您的应用程序中。

    我发现设计能够报告其配置并对其进行验证的应用程序非常有价值。在大多数情况下,缺少或无效的配置项会导致应用程序中止。尽可能在启动时执行验证(和中止)= 快速失败。只有在可以可靠使用硬代码默认值时。

    抽象配置访问,以便大多数应用程序不知道它来自何处或如何处理。我更喜欢创建Config 类,将可配置设置公开为单独的属性(相关时强类型化),然后我通过 IOC 将它们“注入”到应用程序类中。不要让所有应用程序类直接调用所选平台的原始配置框架;抽象是你的朋友。

    在大多数企业级(财富 500 强)组织中,除了该环境的管理团队之外,没有人看到生产(甚至测试)环境配置。配置文件永远不会在发布中部署,它们是由管理团队手动编辑的。相关的配置文件肯定永远不会与代码并排检查到源代码控制中。管理团队可能会使用源代码控制,但它是他们自己的私有存储库。 Sarbanes-Oxley 和类似法规也倾向于严格禁止开发人员对(近)生产系统或任何敏感配置数据进行一般访问。在设计方法时请注意。

    享受吧。

    【讨论】:

    • 即使我不同意您对我的回答的评论,我发现您的内容也很丰富。 +1
    【解决方案2】:

    您应该始终将历史记录(源代码控制的用途)与部署分开。

    部署涉及:

    • 一组已识别的数据(SCM 提供的标签或标签派上用场)
    • 一个处理这些数据的进程(至少将它们复制到正确的位置,还可以扩展一些压缩文件,等等...)

    在部署执行的各种操作中,您应该包括一个去变量化阶段。

    变量是一个关键字,表示可能会根据您的部署平台(可以是用于持续集成的 PC、用于基本认证的 linux、用于预生产认证的旧 Solaris8 以及带区域的完整 F15K Solaris10)的关键字对于生产:它很短,它可以变化很大)。实例见Jonathan Leffler's answer

    一个变量可以代表一个路径、一个JVM版本、一些JVM设置等等,你放入SCM的应该是一个包含变量的数据,而不是硬编码的设置。

    下一步是在您的可执行文件中包含一种方法来检测设置文件中的任何更改,以便在运行某些参数时进行更新(避免所有“关闭/更改设置/重新启动”序列)。
    这意味着它们是两种类型的部署变量

    • 静态(永远不会改变),
    • 动态(最好在运行时会话中考虑)

    【讨论】:

    • 请参阅 Jonathan Leffler 的回答 cmets。在执行期间更改配置是危险的(与其他上下文交互),但在极少数情况下可能是必要的。
    • 我不同意。在你的生产环境中可能。不在我们的。当你有一大群服务器需要微调时,这种情况很少见。请考虑您可能没有见过您职业生涯中的每一个生产场景。我知道我没有。
    • Rob Williams:“计算机顾问,在各种技术、角色和行业方面拥有大约 30 年的经验”......好吧,仔细想想,实际上你可能已经看到了这一切;)而且我的答案可能写得不太好。
    • @VonC:我同意:对于我们这些在草原上漫游的人来说,有些例外似乎并不例外。我试图对我们的大多数读者可能永远不会看到大型服务器场这一事实保持敏感。希望当他们这样做时,他们会知道如何破例。
    【解决方案3】:

    尽可能避免使用绝对路径。

    不要依赖您当前的版本控制来做一些神奇的事情 - 您将来可能会更改版本控制系统。

    最简单的方法对我有用:有一个“config.live”,并且为开发配置了“config”。在部署期间,只需将 config.live 移动到 config 就可以了。对于更复杂的配置,可能需要每个配置的子目录。

    一套部署程序是必不可少的 - 因为配置只是一个不同的领域。

    任何更复杂的事情几乎肯定会导致比它解决的问题更多的问题。

    【讨论】:

      【解决方案4】:

      使用 Git 等 SCM 进行版本控制和部署工具 such as Capistrano for deployment。虽然 Capistrano 最初是为 Ruby on Rails 创建的,但它完全可以用于其他框架和语言。

      主要的是,特定的部署工具可以让您灵活地在两端自动化诸如路径之类的事情。

      【讨论】:

        【解决方案5】:

        我喜欢 Ruby on Rails 处理此类问题的方式 - 特定于环境的配置文件。 Rails 支持开发、测试和生产数据库连接——由 database.yml 文件中的配置控制。这是一篇关于创建其他特定于环境的配置选项的博客文章,它适用于 Rails,但可能会给你一些关于如何为你的环境做类似事情的想法。 http://usablewebapps.com/2008/09/yaml-and-custom-config-for-rails-projects/

        【讨论】:

          【解决方案6】:

          听起来你的生产代码是完整的 git 存储库,要更新生产你做一个git pull?您可能想尝试一个单独的构建过程,从存储库中检查代码并创建一个干净的构建(没有 .git 文件夹)。您可以拥有特定于环境的配置文件,其中包含与它一起复制或创建的路径。

          【讨论】:

            猜你喜欢
            • 2010-09-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-23
            • 2015-02-13
            • 1970-01-01
            • 2011-01-02
            • 2010-09-24
            相关资源
            最近更新 更多