La mejor manera de leer un archivo de configuración en bash


23

¿Cuál es la mejor manera de leer un archivo de configuración en bash?
Por ejemplo, tiene un script y no está dispuesto a completar toda la configuración manualmente cada vez que llama al script.

Edición 1: creo que no lo dejé claro, así que: lo que quiero es ... Tengo un archivo de configuración que es como

variable_name value  
variable_name value ...  

y quiero leer eso Sé que podría entenderlo por los argumentos que estoy buscando más o menos ... pero tal vez haya una forma más inteligente :)


2
Tendrás que mostrar a qué tipo de configuración te refieres. Proporcione un ejemplo.
Muru

Vea también una pregunta muy similar sobre el StackExchange de Unix y Linux.
Michael

Respuestas:


38

Como dijo mbiber, sourceotro archivo. Por ejemplo, su archivo de configuración (digamos some.config) sería:

var1=val1
var2=val2

Y tu guión podría verse así:

#! /bin/bash

# Optionally, set default values
# var1="default value for var1"
# var1="default value for var2"

. /path/to/some.config

echo "$var1" "$var2"

Los muchos archivos /etc/defaultgeneralmente sirven como archivos de configuración para otros scripts de shell de manera similar. Un ejemplo muy común de publicaciones aquí es /etc/default/grub. Este archivo se utiliza para establecer las opciones de configuración de GRUB, ya que grub-mkconfiges un script de shell que lo genera:

sysconfdir="/etc"
#…
if test -f ${sysconfdir}/default/grub ; then
  . ${sysconfdir}/default/grub
fi

Si realmente debe procesar la configuración del formulario:

var1 some value 1
var2 some value 2

Entonces podrías hacer algo como:

while read var value
do
    export "$var"="$value"
done < /path/to/some.config

(También podría hacer algo como eval "$var=$value", pero eso es más riesgoso que obtener un script. Inadvertidamente podría romperlo más fácilmente que un archivo de origen).


Esa es una excelente manera, podría usar el espacio en blanco sustituto de sed para "="
IcyIcyIce

1
@IcyIcyIce Simplemente no lo hagas. ¿Por qué no puedes escribirlo =desde el principio?
Muru

1
@IcyIcyIce Así es como se supone que debe ser. Puede usar el código de shell en los diversos archivos en /etc/default, y principalmente para un buen uso. Si su usuario despistado tiene acceso a la configuración de algo que se ejecuta como root, ya es una causa perdida.
Muru

1
@IcyIcyIce haga que sus maestros aclaren lo que quieren. Una parte del aprendizaje para desarrollar software es conocer los requisitos con claridad.
muru

1
@IcyIcyIce ver actualización.
Muru

4

Obviamente, no soy el bashespecialista aquí, pero el concepto no debería ser diferente en el idioma que uses:

Un ejemplo

En el ejemplo a continuación, puede usar un script (muy) básico para establecer una cadena o imprimir una cadena, como se establece en su archivo de configuración:

#!/bin/bash

# argument to set a new string or print the set string
arg=$1
# possible string as second argument
string=$2
# path to your config file
configfile="$HOME/stringfile"

# if the argument is: "set", write the string (second argument) to a file
if [ "$arg" == "set" ]
then
echo "$string" > $configfile 
# if the argunment is "print": print out the set string, as defined in your file
elif [ "$arg" == "print" ]
then 
echo "$( cat $configfile )"
fi

Luego

  • Para establecer una cadena en su archivo de configuración:

    $ '/home/jacob/Bureaublad/test.sh' set "Een aap op een fiets, hoe vind je zoiets?"
  • Posteriormente, para imprimir la cadena, como se define en su "archivo de configuración":

    $ '/home/jacob/Bureaublad/test.sh' print
    Een aap op een fiets, hoe vind je zoiets?

Por supuesto, en una secuencia de comandos aplicada real, debe agregar muchas cosas para asegurarse de que los argumentos sean correctos, decidir qué hacer cuando la entrada es incorrecta, el archivo de configuración no existe, etc., pero:

Esta es la idea basica


gracias, solo estoy actualizando la pregunta, creo que no lo
dejé

4

Use sourceo .para cargar en un archivo.

source /path/to/file

o

. /path/to/file

También se recomienda verificar si el archivo existe antes de cargarlo porque no desea continuar ejecutando su script si no hay un archivo de configuración.


0

Estoy usando este ...

#!/bin/bash

CFG_FILE=/etc/test.conf
CFG_CONTENT=$(cat $CFG_FILE | sed -r '/[^=]+=[^=]+/!d' | sed -r 's/\s+=\s/=/g')
eval "$CFG_CONTENT"

El archivo Conf se analiza con sed y luego se evalúa como tareas variables simples

Primer análisis de valores clave de sed (admite también = rodeado de espacios)

Second sed elimina espacios alrededor = signo para asignación variable válida

Se puede agregar más tratamiento de sed.

Se eliminarán todos los demás textos que no coincidan en el archivo conf (incluidos # o; comentario y otros)

¡Tenga en cuenta que los comandos de shell de una sola línea también se pueden evaluar desde este archivo de configuración!


1
Uso inútil decat . ¿Por qué invocas seddos veces seguidas? Puede encadenar sedcomandos de esta manera:sed -r '/[^=]+=[^=]+/!d;s/\s+=\s/=/g'
David Foerster

Además, este sedcomando generará una salida vacía para las entradas del archivo de configuración de muestra en la pregunta. -1
David Foerster

1
Otra posible mejora: use el .comando y la redirección del proceso en lugar de variables temporales para mantener la salida del subproceso:. <(sed ... "$CFG_FILE")
David Foerster

Por supuesto, mi ejemplo usa clave = valor como el archivo de configuración. Es una mejor práctica que el "valor clave". Usando key = value mi ejemplo funciona. Su encadenamiento de comandos sed es mejor, lo admito, pero el comando fuente espera un archivo para que podamos usar: eval $(sed -r '/[^=]+=[^=]+/!d;s/\s+=\s/=/g' "$CFG_FILE")que es mucho mejor para entender lo que está sucediendo.
smARTin

Sí, .espera que un archivo y la sustitución del proceso se expanda a un archivo. . <(echo echo foo)funciona exactamente como se esperaba en Bash v4.3.11. En pequeños ejemplos, probablemente no importará. Sin embargo, prefiero no pasar varios kilobytes a través de la sustitución de comandos.
David Foerster

0
#------------------------------------------------------------------------------
# parse the ini like $0.$host_name.cnf and set the variables
# cleans the unneeded during after run-time stuff. Note the MainSection
# courtesy of : http://mark.aufflick.com/blog/2007/11/08/parsing-ini-files-with-sed
#------------------------------------------------------------------------------
doParseConfFile(){
    # set a default cnfiguration file
    cnf_file="$run_unit_bash_dir/$run_unit.cnf"

    # however if there is a host dependant cnf file override it
    test -f "$run_unit_bash_dir/$run_unit.$host_name.cnf" \
    && cnf_file="$run_unit_bash_dir/$run_unit.$host_name.cnf"

    # yet finally override if passed as argument to this function
    # if the the ini file is not passed define the default host independant ini file
    test -z "$1" || cnf_file=$1;shift 1;


    test -z "$2" || ini_section=$2;shift 1;
    doLog "DEBUG read configuration file : $cnf_file"
    doLog "INFO read [$ini_section] section from config file"

    # debug echo "@doParseConfFile cnf_file:: $cnf_file"
    # coud be later on parametrized ...
    test -z "$ini_section" && ini_section='MAIN_SETTINGS'

    doLog "DEBUG reading: the following configuration file"
    doLog "DEBUG ""$cnf_file"
    ( set -o posix ; set ) | sort >"$tmp_dir/vars.before"

    eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
        -e 's/#.*$//' \
        -e 's/[[:space:]]*$//' \
        -e 's/^[[:space:]]*//' \
        -e "s/^\(.*\)=\([^\"']*\)$/\1=\"\2\"/" \
        < $cnf_file \
        | sed -n -e "/^\[$ini_section\]/,/^\s*\[/{/^[^#].*\=.*/p;}"`

    ( set -o posix ; set ) | sort >"$tmp_dir/vars.after"

    doLog "INFO added the following vars from section: [$ini_section]"
    cmd="$(comm -3 $tmp_dir/vars.before $tmp_dir/vars.after | perl -ne 's#\s+##g;print "\n $_ "' )"
    echo -e "$cmd"
    echo -e "$cmd" >> $log_file
    echo -e "\n\n"
    sleep 1; printf "\033[2J";printf "\033[0;0H" # and clear the screen
}
#eof func doParseConfFile
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.