Créer un nouveau fichier à partir de modèles avec un script bash

Je dois créer des fichiers de configuration 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 parameters changent d’un fichier à un autre ( listen_port , domain, path sur server …).

Comme toute erreur dans ces fichiers entraîne un dysfonctionnement du service, j’aimerais créer ces fichiers en utilisant un script bash.

Par exemple:

 generate_new_http_service.sh 8282 subdomain.domain.com /home/myapp/rootOfHTTPService 

Je cherche une sorte de module de template que je pourrais utiliser avec bash. Ce module de modélisation utilisera des scripts conf et init.d génériques pour en créer de nouveaux.

Avez-vous des indices pour cela? Sinon, je pourrais utiliser le moteur de template Python.

    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 de modèle pour bash? Utilisez sed , Luke! Voici un exemple de l’un des millions de moyens possibles:

     $ 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. Ecrivez un script comme celui-ci:

     #!/bin/bash cat < 

    alors appelez-le ainsi:

     foo=FOO bar=BAR ./template 

    Pour la génération de fichier simple, faites essentiellement

      . "${config_file}" template_str=$(cat "${template_file}") eval "echo \"${template_str}\"" 

    suffirait.

    Ici, ${config_file} contient les variables de configuration au format ${config_file} par shell, et ${template_file} est le fichier modèle qui ressemble au shell ici document. La première ligne source du fichier ${config_file} , la deuxième ligne place 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 double "${template_str}" est développée) et l’évalue.

    Pour un exemple du contenu de ces deux fichiers, reportez-vous à 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 une sortie de shell. De plus, si le fichier de modèle est produit en externe, vous devez envisager de mettre en place un filtrage approprié avant l’exécution afin d’éviter de perdre vos fichiers lorsque quelqu’un injecte le fameux $(rm -rf /) dans le fichier de modèle. .

    Voici l’approche que j’ai finalement prise pour résoudre ce problème. Je l’ai trouvé un peu plus flexible que certaines des approches ci-dessus, et cela évite certains 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. 

    config:

     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. 

    Vous pouvez utiliser la classe python ssortingng.Template

     $ echo 'before $X after' > template.txt $ python -c 'import ssortingng; print(ssortingng.Template(open("template.txt").read()).substitute({"X":"A"}))' before A after 

    ou

     $ python -c 'import ssortingng, sys; print(ssortingng.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 un mappage 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 nous substituons l’espace réservé à l’argument de la ligne de commande.

    Sinon, vous pouvez utiliser 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 de la variable d’environnement. X=A définit la variable d’environnement sur la valeur souhaitée.

    Voici comment j’ai fait pour moi:

     . "${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 à créer de variable supplémentaire.