我想制作一个更新配置文件的 shell 脚本。
服务器上存在的文件包含信息,例如各种 IP 地址。
新文件有更多代码,来自添加到系统的新配置,我希望能够将这些新配置添加到服务器文件,而不更改那里已经配置的内容
例子:
服务器文件
[config]
ip=127.0.0.1
port=22
新文件
[config]
ip=XXX.XXX.XXX.XXX
port=XX
user=root
我希望生成的文件是
[config]
ip=127.0.0.1
port=22
user=root
怎样才是一个好方法呢?我不想依赖行位置等,因为实际的配置文件非常大,可以将更多行添加到服务器文件中。
我尝试对文件进行比较并应用补丁,但没有成功。
谢谢你的帮助。
答案1
正如吉尔斯所说,您需要使用一个了解配置文件格式的工具。对于您的特定示例,您可以使用一个简短的 Python 脚本,该脚本使用内置的配置解析器模块。
首先,假设服务器上的原始配置文件是
original.cfg
:[config] ip=127.0.0.1 port=22
现在将您的更改放入一个名为的新文件中
update.cfg
:[config] user=root
该文件应该在您希望它们所在的部分标题下列出新的或更改的条目。
然后运行如下脚本:
#!/usr/bin/env python import ConfigParser config = ConfigParser.ConfigParser() # Read the original config file with open('original.cfg', 'r') as f: config.readfp(f) # Also read in all the changes we'd like to make with open('update.cfg', 'r') as f: config.readfp(f) # Write the full new config file out with open('output.cfg', 'w') as f: config.write(f)
当然,如何做到这一点有很多变化。例如,配置更改可以直接编码到 Python 脚本中,而不是从单独的update.cfg
文件中读取。不过,这应该为您提供良好的入门基础。
答案2
使用您喜欢的任何程序将它们解析为两个单独的数据集。我将使用 common lisp 并将每个配置文件存储为列表的嵌套列表。
然后使用语言工具进行合并/修补/联合/设置差异等。从较高的层次来看,对于一侧差异,代码可能如下所示:
(union
(vals A :keys 'all)
(vals B
:keys
(set-difference
(keys B)
(keys A))))
然后将生成的数据集写入文件。
答案3
我用配置对象用于此目的的 Python 库。如果这样做,确实需要编写 Python 来与配置文件交互。我通常有一个default_conf
具有默认值的文件,并且我可以有选择地用其他一些文件覆盖这些设置,例如user_conf
这是我当前用作示例的代码。函数的后半部分是验证,这很重要,但您可以忽略它以进行第一个近似。对于您所做的使用
conf = get_conf()
ip = conf["ip"]
在您的情况下,我猜想服务器文件是覆盖的文件,尽管更常见的是用户文件覆盖系统文件。这当然是 Unix 类型系统中的用户约定。
要将 ConfigObj 对象写入文件,您要做的第一个近似(如果config
是您的对象,如下面的脚本所示)
config.filename = filename
config.write()
因此,如果需要,您可以修改下面的函数以写入文件,而不是返回配置对象。看编写配置文件了解更多细节。
def get_conf():
import configobj, validate, sys
try:
config = configobj.ConfigObj('default_conf', configspec='conf.validate', raise_errors=True)
except configobj.ConfigObjError:
print "ERROR FOR CONFIG FILE 'default_conf':"
raise
try:
user = configobj.ConfigObj('user_conf', configspec='conf.validate', raise_errors=True)
except configobj.ConfigObjError:
print "ERROR FOR CONFIG FILE 'user_conf':"
raise
config.merge(user)
#This is config file validation
fdict = {'check_list_of_list_of_integers': list_of_list_of_integers}
validator = validate.Validator(fdict)
results = config.validate(validator, preserve_errors=True)
if results != True:
for entry in configobj.flatten_errors(config, results):
# each entry is a tuple
section_list, key, error = entry
if key is not None:
section_list.append(key)
else:
section_list.append('[missing section]')
section_string = ', '.join(section_list)
if error == False:
error = 'Missing value or section.'
print section_string, ' = ', error
sys.exit(1)
return config
2015 年 12 月 16 日更新:像 YAML 这样的东西可能是更好的通用解决方案。我建议用它来代替 ConfigObj。一方面,它更加灵活。