¿Cómo hacer y aplicar (parche) un lado diff?

Quiero hacer un script de shell que actualice un file de configuration.

El file presente en el server tiene información, como varias direcciones IP.

El nuevo file tiene más código, desde las nuevas configuraciones agregadas al sistema, quiero poder agregar estas nuevas configuraciones al file del server sin cambiar lo que ya está configurado allí

ejemplo:

file de server

[config] ip=127.0.0.1 port=22 

file nuevo

 [config] ip=XXX.XXX.XXX.XXX port=XX user=root 

Quiero que el file resultante sea

 [config] ip=127.0.0.1 port=22 user=root 

¿Cómo sería una buena manera de hacer eso? No quiero confiar en la position de la línea y demás, porque los files de configuration reales son bastante grandes y se podrían haber agregado más líneas al file del server.

Intenté hacer una diferencia con los files y aplicar el parche, pero no funcionó.

Gracias por cualquier ayuda.

Como dice Gilles, necesitarás usar una herramienta que sepa sobre el formatting de tus files de configuration. Para su ejemplo particular, puede usar un script corto de Python que use el module ConfigParser incorporado .

  • Primero, digamos que su file de configuration original en el server es original.cfg :

     [config] ip=127.0.0.1 port=22 
  • Ahora ponga sus cambios en un nuevo file llamado update.cfg :

     [config] user=root 

    Este file debe tener inputs nuevas o modificadas enumeradas en el encabezado de la sección donde le gustaría que fueran.

  • Luego ejecute un script como este:

     #!/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) 

Hay, por supuesto, muchas variaciones sobre cómo hacer esto. Por ejemplo, los cambios de configuration podrían codificarse directamente en el script de Python en lugar de leerse en un file update.cfg separado. Sin embargo, esto debería darte una buena base para comenzar.

Analícelos en dos sets de datos separados con el progtwig que prefiera. Usaría lisp común y almacenaría cada file de configuration como una list anidada de lists.

Y luego use las herramientas de lenguaje para hacer la fusión / parcheo / unión / set-difference / etc. En un nivel alto, para una diferencia unilateral, el código podría verse así:

 (union (vals A :keys 'all) (vals B :keys (set-difference (keys B) (keys A)))) 

Y luego escribe el set de datos resultante en un file.

Utilizo la biblioteca ConfigObj Python para esto. Si hace esto, se requiere escribir Python para interactuar con los files de configuration. Normalmente tengo un file default_conf que tiene valores pnetworkingeterminados, y puedo anular selectivamente estos ajustes con algún otro file, por ejemplo user_conf

Aquí está el código que estoy usando actualmente como ejemplo. La segunda mitad de la function es la validation, que es importante, pero puede ignorarla en una primera aproximación. Para el uso que haces

 conf = get_conf() ip = conf["ip"] 

En su caso, creo que el file del server es el que sobrescribe, aunque más generalmente es el file del usuario el que anula el file del sistema. Esa es ciertamente la convención del usuario en los sistemas de tipo Unix.

Para escribir un object ConfigObj en un file, en una primera aproximación lo hace (si config es su object como en el script a continuación)

 config.filename = filename config.write() 

De modo que podría modificar la function siguiente para escribir en un file en lugar de devolver el object config si lo desea. Ver Escribir un file de configuration para un poco más de detalle.

 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 

ACTUALIZACIÓN 16 de diciembre de 2015: algo como YAML es probablemente una mejor solución general. Lo recomiendo en lugar de ConfigObj. Por un lado, es más flexible.