Créer un nouveau fichier à partir de modèles avec le script bash
Je dois créer des fichiers conf et init.d
qui sont très similaires. Ces fichiers permettent de déployer un nouveau service http sur mes serveurs. Ces fichiers sont les mêmes et seuls certains paramètres changent d'un fichier à l'autre (listen_port
, Domaine, chemin sur le serveur...).
Comme toute erreur dans ces fichiers conduit à un mauvais fonctionnement du service, je voudrais créer ces fichiers en utilisant un script bash.
Par exemple:
generate_new_http_service.sh 8282 subdomain.domain.com /home/myapp/rootOfHTTPService
Je suis à la recherche d'une sorte de module de Template que je pourrais utiliser avec bash. Ce le module de modèle utiliserait une conf générique et init.d scripts pour en créer de nouveaux.
Avez-vous des indices pour cela? Sinon, je pourrais utiliser le moteur Python templating.
7 réponses
Vous pouvez le faire en utilisant un heredoc. par exemple
Generate.sh:
#!/bin/sh
#define parameters which are passed in.
PORT=$1
DOMAIN=$2
#define the template.
cat << EOF
This is my template.
Port is $PORT
Domain is $DOMAIN
EOF
Sortie:
$ generate.sh 8080 domain.com
This is my template.
Port is 8080
Domain is domain.com
Ou enregistrez - le dans un fichier:
$ generate.sh 8080 domain.com > result
Module modèle pour bash? Utilisez sed
, Luke! Voici un exemple de l'un des millions de façons possibles de le faire:
$ cat template.txt
#!/bin/sh
echo Hello, I am a server running from %DIR% and listening for connection at %HOST% on port %PORT% and my configuration file is %DIR%/server.conf
$ cat create.sh
#!/bin/sh
sed -e "s;%PORT%;$1;g" -e "s;%HOST%;$2;g" -e "s;%DIR%;$3;g" template.txt > script.sh
$ bash ./create.sh 1986 example.com /tmp
$ bash ./script.sh
Hello, I am a server running from /tmp and listening for connection at example.com on port 1986 and my configuration file is /tmp/server.conf
$
Vous pouvez le faire directement dans bash, vous n'avez même pas besoin de sed. Ecrire un script comme ça:
#!/bin/bash
cat <<END
this is a template
with $foo
and $bar
END
Alors appelez-le comme ceci:
foo=FOO bar=BAR ./template
Pour la génération de fichiers simple, en faisant essentiellement
. "${config_file}"
template_str=$(cat "${template_file}")
eval "echo \"${template_str}\""
Suffirait.
Ici ${config_file}
contient les variables de configuration au format shell analysable, et ${template_file}
est le fichier modèle qui ressemble au document shell here. La première ligne de sources dans le fichier ${config_file}
, la deuxième ligne met le contenu du fichier ${template_file}
dans la variable shell template_str
. Enfin, dans la troisième ligne, nous construisons la commande shell echo "${template_str}"
(où l'expression entre guillemets doubles "${template_str}"
est développée) et évaluons il.
Pour un exemple du contenu de ces deux fichiers, veuillez vous référer à la https://serverfault.com/a/699377/120756.
Il y a des limites à ce que vous pouvez avoir dans le fichier de modèle ou vous devez effectuer un échappement de shell. De plus, si le fichier modèle est produit en externe, pour des raisons de sécurité, vous devez envisager d'implémenter un filtrage approprié avant l'exécution afin que vous ne perdiez pas vos fichiers lorsque quelqu'un injecte le fameux $(rm -rf /)
dans le fichier. fichier de modèle.
Voici l'approche que j'ai fini par prendre pour résoudre ce problème. Je l'ai trouvé un peu plus flexible que certaines des approches ci-dessus, et cela évite certains des problèmes avec les citations.
Fill.sh:
#!/usr/bin/env sh
config="$1"
template="$2"
destination="$3"
cp "$template" "$destination"
while read line; do
setting="$( echo "$line" | cut -d '=' -f 1 )"
value="$( echo "$line" | cut -d '=' -f 2- )"
sed -i -e "s;%${setting}%;${value};g" "$destination"
done < "$config"
Modèle:
Template full of important %THINGS%
"Note that quoted %FIELDS% are handled correctly"
If I need %NEWLINES% then I can add them as well.
Configuration:
THINGS=stuff
FIELDS="values work too!"
NEWLINES="those\\nnifty\\nlinebreaks"
Résultat: Modèle plein de choses importantes
"Note that quoted "values work too!" are handled correctly"
If I need those
nifty
linebreaks then I can add them as well.
Voici comment je l'ai fait pour moi-même:
. "${config_file}"
eval "cat << EOF
$(cat ${template_file})
EOF"
Et si vous voulez le mettre dans un fichier de configuration:
. "${config_file}"
eval "cat > /etc/MY_SERVICE/MY_CONFIG << EOF
$(cat ${template_file})
EOF"
De cette façon, vous n'avez pas besoin de créer de variable supplémentaire.
Vous pouvez utiliser la classe python string.Template
$ echo 'before $X after' > template.txt
$ python -c 'import string; print(string.Template(open("template.txt").read()).substitute({"X":"A"}))'
before A after
Ou
$ python -c 'import string, sys; print(string.Template(open("template.txt").read()).substitute({"X":sys.argv[1]}))' "A"
Ici $X
est un espace réservé dans le modèle et {"X":"A"}
est une cartographie de l'espace réservé à une valeur. Dans le code python, nous lisons le texte du modèle à partir du fichier, en créons un modèle, puis substituons l'espace réservé à l'argument de ligne de commande.
Vous pouvez également utiliser L'ERB de Ruby, si Ruby est installé sur votre machine.
$ echo "before <%= ENV['X'] %> after" > template.txt
$ X=A erb template.txt
before A after
Ici <%= ENV['X'] %>
est un espace réservé. ENV['X']
Lit la valeur du variable d'environnement. X=A
définit la variable d'environnement à la valeur désirée.