174 votes

Bash Templating: Comment construire des fichiers de configuration à partir de modèles avec Bash?

Je suis d'écrire un script pour automatiser la création de fichiers de configuration pour Apache et PHP pour mon propre serveur. Je ne veux pas utiliser toutes les Interfaces graphiques comme CPanel ou ISPConfig.

J'ai quelques modèles de Apache et PHP, les fichiers de configuration. Script Bash besoin de lire des modèles, de faire la substitution des variables de sortie et analysé des modèles dans un dossier. Quelle est la meilleure façon de le faire? Je peux penser à plusieurs égards. Qui est le meilleur ou peut-être il y a quelques meilleures façons de le faire? Je veux le faire dans le plus pur Bash (c'est facile en PHP par exemple)

1) Comment remplacer ${} emplacements dans un fichier texte?

template.txt:

the number is ${i}
the word is ${word}

script.sh:

#!/bin/sh

#set variables
i=1
word="dog"
#read in template one line at the time, and replace variables
#(more natural (and efficient) way, thanks to Jonathan Leffler)
while read line
do
    eval echo "$line"
done < "./template.txt"

BTW, comment puis-je rediriger la sortie dans un fichier externe? Ai-je besoin pour échapper à quelque chose si les variables contiennent, disons, d'un devis?

2) à l'Aide de cat & sed pour remplacer chaque variable par sa valeur:

Compte tenu de template.txt:

The number is ${i}
The word is ${word}

Commande:

cat template.txt | sed -e "s/\${i}/1/" | sed -e "s/\${word}/dog/"

Semble mauvais pour moi à cause de la nécessité d'échapper à de nombreux symboles différents et avec de nombreuses variables, la ligne sera tooooo de long.

Pouvez-vous penser à d'autres élégante et sûre solution?

211voto

yottatsa Points 261

Essayez envsubst

 FOO=foo
BAR=bar
export FOO BAR

envsubst <<EOF
FOO is $FOO
BAR is $BAR
EOF
 

73voto

Dan Garthwaite Points 668

envsubst était nouveau pour moi. Fantastique.

Pour mémoire, utiliser un heredoc est un excellent moyen de modéliser un fichier de configuration.

 STATUS_URI="/hows-it-goin";  MONITOR_IP="10.10.2.15";

cat >/etc/apache2/conf.d/mod_status.conf <<EOF
<Location ${STATUS_URI}>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from ${MONITOR_IP}
</Location>
EOF
 

69voto

ZyX Points 26516

Vous pouvez utiliser ceci:

 perl -p -i -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : $&/eg' < template.txt
 

pour remplacer toutes les chaînes ${...} par les variables d'environnement correspondantes (n'oubliez pas de les exporter avant d'exécuter ce script).

Pour pur bash, cela devrait fonctionner (en supposant que les variables ne contiennent pas de chaînes $ {...}):

 #!/bin/bash
while read line ; do
    while [[ "$line" =~ '(\$\{[a-zA-Z_][a-zA-Z_0-9]*\})' ]] ; do
        LHS=${BASH_REMATCH[1]}
        RHS="$(eval echo "\"$LHS\"")"
        line=${line//$LHS/$RHS}
    done
    echo $line
done
 

41voto

Hai Vu Points 10359

Je suis d’accord avec l’utilisation de sed: c’est le meilleur outil de recherche / remplacement. Voici mon approche:

 $ cat template.txt
the number is ${i}
the dog's name is ${name}

$ cat replace.sed
s/${i}/5/
s/${name}/Fido/

$ sed -f replace.sed template.txt > out.txt

$ cat out.txt
the number is 5
the dog's name is Fido
 

26voto

mogsie Points 1998

Je pense que eval fonctionne vraiment bien. Il gère les modèles de avec mais les sauts de ligne, les espaces et toutes sortes de bash choses. Si vous avez le plein contrôle sur les modèles eux-mêmes, bien sûr:

$ cat template.txt
variable1 = ${variable1}
variable2 = $variable2
my-ip = $(curl -s ifconfig.me)
$ echo $variable1
AAA
$ echo $variable2
BBB
$ eval "echo \"$(<template.txt)\"" 2> /dev/null
variable1 = AAA
variable2 = BBB
my-ip = 11.22.33.44

Cette méthode doit être utilisée avec soin, bien sûr, depuis eval peut exécuter du code arbitraire. L'exécution de ce que la racine est à peu près hors de question.

Vous pouvez également utiliser ici des documents si vous préférez cat de echo

$ eval "cat <<< \"$(<template.txt)\"" 2> /dev/null

Edit: Retiré la partie sur l'exécution de ce en tant que root avec la commande sudo...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X