在 Linux 应用程序中,我不想使用“我自己的”配置解析器,而是使用(应该是?)已经可用的配置解析器。简单,保持应用程序配置的维护简单,并且不添加额外的库。
答案1
确实没有“标准”配置解析器库。如果您仔细阅读/etc
,您会发现以下一些组合:
- XML配置
- Windows INI 样式配置
- 基本 KEY=VALUE 配置
- JSON(主要出现在 Web 应用程序中)。
- YAML(主要出现在较新的东西中,尤其是用 Python 编写的)。
- 看起来像 JSON 或 YAML 或 XML,但实际上不是的东西(例如,请参阅 Nginx 配置(看起来像 JSON,但不是)、Apache(看起来像 XML,但不是)和 Unbound(看起来像 YAML) ,但不是)。
- 各种 shell 语言。
- 各种看似 shell 语言但技术上并非如此的东西。
- 各种脚本语言的源代码片段。
- 可能还有其他我没想到的事情。
至于您的应用程序使用什么:
- 为了热爱所有神圣的事物,请避免使用 XML。它不必要地冗长,解析起来非常复杂(因此需要很长时间和大量内存),并且带来了许多安全问题。在元素和属性之间取得适当的平衡也很重要,您通常会在稍后的某个时候后悔对此做出的选择。这里唯一真正的优点是,几乎可以保证您遇到的任何系统上都有一个有效的 XML 解析器。
- Windows 风格的 INI 文件通常是一个安全的选择,尽管它们限制了配置结构的复杂性。为此存在许多库,并且您的系统可能已经至少有一个。它们在 Linux 上并不那么流行(经典配置文件传统上是没有节标题的 KEY=VALUE 对),但它们仍然被广泛使用,并且很容易理解。
- 基本的 KEY=VALUE 对(理想情况下每行一个)解析起来非常简单,您甚至不需要库,但它们的功能非常有限。
- JSON 安全且易于解析,得到广泛支持(现在几乎每种主要语言都至少有一个解析器),并且支持配置结构的任意嵌套。但是,它不支持注释(某些解析器可以,但结果不能互操作),这对于设计用于使用文本编辑器编辑的文件来说不太好。
- YAML 是我个人最喜欢的,它相当安全且易于解析,对大多数人来说看起来非常自然,支持注释,并且开销非常小。这里唯一重要的是缩进真的很重要,因为它约占语法的 80%,再加上 YAML 需要缩进空格(无制表符)这一事实,如果您没有好的编辑器,那么使用它可能会有点麻烦。
- 如果您使用脚本语言,您可能会考虑使用源代码片段进行配置,但是非常小心做这件事。除非您非常小心地解析它们,否则您几乎可以让用户根据需要对您的内部逻辑执行任意操作,这是客户支持的噩梦(您将要最终让人们抱怨你破坏了他们的配置,其中恰好包括你更改的核心程序内部的内容)。
答案2
一标准我想到的配置解析器是用于设置环境变量的 shell 代码。
如果您的软件是由执行以下操作的程序启动的:
#! /bin/sh -
set -o allexport
for conf in /etc/default/mysoft ~/.config/mysoft.conf; do
[ -f "$conf" ] && [ -r "$conf" ] && . "$conf"
done
unset -v conf
exec mysoft "$@"
然后您的用户可以创建一些~/.config/mysoft.conf
内容如下:
MYSOFT_TUNABLE=foo
# even using shell code to set the values:
MYSOFT_MAX_COLUMNS=$((${COLUMNS:-$(tput cols)} / 2))
并且可以使用其编写的语言mysoft
使用相应的 API 查询这些值。getenv("MYSOFT_TUNABLE")
这仅限于平面key=value
,但value
仅限于非 NUL 字符的字符串。如果您需要更复杂的数据结构,可以查看 JSON 或 XML,大多数语言都有一个或多个解析库。
php
对于用解释语言(例如,,,perl
... )编写的软件python
,常见的简单且非常灵活的方法是将配置文件编写为这些语言的源文件。
例如,对于perl
,创建一个~/.config/mysoft/conf.pl
as:
%conf = (
string_param => "string",
list_param => [1, 2],
complex_param => { foo => "bar", bar => "baz" }
);
以编程方式生成这些也很简单。
对于sh
,您可以只使用export -p
:
setenv("MYSOFT_TUNABLE", "bar");
system("export -p MYSOFT_TUNABLE MYSOFT_MAX_COLUMS > ~/.conf/mysoft.conf");
或者与perl
:
use Data::Dumper;
print Data::Dumper->Dump([\%conf], ["*conf"]);