Un servidor de bases de datos con muchas instancias cambió su nombre de host, por razones que no vienen al caso. Al hacer esto, es necesario cambiar la configuración de todas las aplicaciones que hacen uso de las bases de datos alojadas en el mismo para que apunten al nuevo host (de lo contrario no podrán acceder a las bases de datos y por ende no funcionarán). Afortunadamente todas las aplicaciones se encuentran en el mismo servidor, con lo cual no es necesario recurrir a Ansible para editar archivos en múltiples servidores al mismo tiempo. Sin embargo, la cantidad de aplicaciones que se conectan al servidor de bases de datos es enorme:

root@www:/usr/local/apps# ls -1 . | wc -l
98

98 aplicaciones en total, en las cuales se debe cambiar el valor de la variable db_host en cada archivo de configuración config.ini. ¿Cómo hacer para no tener que editar 98 archivos de configuración a mano? Este artículo demuestra cómo utilizar find y sed en conjunto para buscar todos los archivos de configuración config.ini y cambiar una cadena en cada uno de ellos.

Peor aún cuando dentro del archivo de configuración (no viene al caso explicar por qué) el nombre de host del servidor de bases de datos está replicado 3 veces:

root@www:/usr/local/apps# grep db_host app_v0.2.35/config/config.ini 
db_host = db.linuxito.com
db_host = db.linuxito.com
db_host = db.linuxito.com

Lo que se debe hacer entonces, partiendo del directorio raíz de las aplicaciones, es:

  1. Buscar todos los archivos cuyo nombre sea config.ini.
  2. Dentro de cada archivo reemplazar el nombre del servidor de bases de datos anterior ("db.linuxito.com") por el nuevo ("db-h01.linuxito.com").

Ya he explicado cómo buscar archivos por nombre utilizando find y cómo editar archivos de texto con sed. Esto se resuelve de la siguiente forma:

  1. find . -type f -name "config.ini"
  2. sed 's/db.linuxito.com/db-h01.linuxito.com/g' config.ini

Ahora bien, una cuestión adicional: el nombre del archivo de configuración puede no ser exactamente "config.ini" sino variantes como "config-www.ini", "config-postgres.ini" u otra (aunque siempre comenzando con "config-" y terminando con extensión ".ini". Así que se debe emplear un comodín en la búsqueda.

Sólo falta el "pegamento" para aplicar sed sobre cada archivo encontrado por find, y es el uso de la opción -exec de find, la cual permite ejecutar cualquier comando sobre cada resultado de la búsqueda. El resultado es el siguiente "oneliner":

find . -type f -name "config-*.ini" -exec sed -i 's/db.linuxito.com/db-h01.linuxito.com/g' {} +

Al utilizar -exec, todos los parámetros que siguen se toman como argumentos del comando, hasta encontrar un ; ó +. El uso de llaves {} indica dónde se ubica (como parámetro al comando) el nombre del archivo encontrado.

La diferencia en el uso de ; y + está en la cantidad de invocaciones al comando pasado como parámetro a -exec. Si se emplea ; se invocará una instancia del comando pasado como parámetro a exec por cada resultado. Mientras que con + se ejecuta una sola instancia con todos los resultados como parámetro.

Para entenderlo mejor supongamos que, a partir del directorio raíz de las aplicaciones, hubiera sólo dos coincidencias: "app_v0.2.35/config/config.ini" y "app_v0.3.1/config/config.ini". Con ; (find . -type f -name "config-*.ini" -exec sed -i 's/db.linuxito.com/db-h01.linuxito.com/g' {} ;) se ejecutarían los siguientes comandos:

sed -i 's/db.linuxito.com/db-h01.linuxito.com/g' app_v0.2.35/config/config.ini
sed -i 's/db.linuxito.com/db-h01.linuxito.com/g' app_v0.3.1/config/config.ini

En cambio con + se ejecutaría sólo el siguiente comando:

sed -i 's/db.linuxito.com/db-h01.linuxito.com/g' app_v0.2.35/config/config.ini app_v0.3.1/config/config.ini

El uso de + es similar a lo que hace la herramienta xargs. En definitiva es una invocación por resultado (;) versus una única invocación para todos los resultados (+).

Finalmente, luego de ejecutar el comando se observa que el nombre de host ha cambiado:

root@www:/usr/local/apps# find . -type f -name "config-*.ini" -exec sed -i 's/db.linuxito.com/db-h01.linuxito.com/g' {} +
root@www:/usr/local/apps# grep db_host app_v0.2.35/config/config.ini
db_host = db-h02.linuxito.com
db_host = db-h02.linuxito.com
db_host = db-h02.linuxito.com

Luego es posible comprobar que no hayan quedado referencias al nombre anterior de forma masiva empleando otra búsqueda, esta vez combinada con grep

root@www:/usr/local/apps# find . -type f -name "config-.ini" -exec grep 'db.linuxito.com' {} +
root@www:/usr/local/apps# echo $?
1

Si el código de retorno es 1, no hubo resultados.

Compartí este artículo