Создание нового файла из шаблонов с помощью скрипта bash
Я должен создать файлы conf и init.d
, которые очень похожи. Эти файлы позволяют развернуть новую службу http на моих серверах. Эти файлы одинаковы, и только некоторые параметры меняются от одного файла к другому (listen_port
, домен, путь на сервере...).
Поскольку любая ошибка в этих файлах приводит к неправильной работе сервиса, я хотел бы создать эти файлы с помощью сценария bash.
Например:
generate_new_http_service.sh 8282 subdomain.domain.com /home/myapp/rootOfHTTPService
Я ищу своего рода модуль шаблонов, который я мог бы использовать с bash. Этот модуль шаблонов будет использовать некоторые общие conf и init.D скрипты для создания новых.
У вас есть намеки на это? Если нет, я мог бы использовать python templating engine.
7 ответов:
Вы можете сделать это с помощью heredoc. например
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
Вывод:
$ generate.sh 8080 domain.com This is my template. Port is 8080 Domain is domain.com
Или сохраните его в файл:
$ generate.sh 8080 domain.com > result
Модуль шаблона для bash? Используй
sed
, Люк! Вот пример одного из миллионов возможных способов сделать это:$ 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 $
Вы можете сделать это прямо в bash, вам даже не нужен sed. Напишите такой сценарий:
#!/bin/bash cat <<END this is a template with $foo and $bar END
Тогда назовем это так:
foo=FOO bar=BAR ./template
Для простой генерации файлов, в основном делая
. "${config_file}" template_str=$(cat "${template_file}") eval "echo \"${template_str}\""
Было бы достаточно.
Здесь
${config_file}
содержит переменные конфигурации в формате Shell parseable, а${template_file}
- файл шаблона, который выглядит как документ shell here. Первая строка является источником в файле${config_file}
, вторая строка помещает содержимое файла${template_file}
в переменную оболочкиtemplate_str
. Наконец, в третьей строке мы строим команду оболочкиecho "${template_str}"
(где расширяется выражение в двойных кавычках"${template_str}"
) и вычисляем оно.Для примера содержимого этих двух файлов, пожалуйста, обратитесь к https://serverfault.com/a/699377/120756 .
Есть ограничения, которые вы можете иметь в файле шаблона или вам нужно выполнить экранирование оболочки. Кроме того, если файл шаблона создается извне, то по соображениям безопасности вам нужно рассмотреть возможность реализации надлежащей фильтрации перед выполнением, чтобы вы, например, не потеряли свои файлы, когда кто-то вводит знаменитый
$(rm -rf /)
в файл шаблона.
Вот подход, который я выбрал для решения этой проблемы. Я нашел его немного более гибким, чем некоторые из вышеупомянутых подходов, и он позволяет избежать некоторых проблем с цитатами.
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"
Шаблон:
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"
Результат: Шаблон, полный важных вещей
"Note that quoted "values work too!" are handled correctly" If I need those nifty linebreaks then I can add them as well.
Вот как я сделал для себя:
. "${config_file}" eval "cat << EOF $(cat ${template_file}) EOF"
И если вы хотите поместить его в конфигурационный файл:
. "${config_file}" eval "cat > /etc/MY_SERVICE/MY_CONFIG << EOF $(cat ${template_file}) EOF"
Таким образом, вам не нужно создавать дополнительную переменную.
Вы можете использовать класс 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
Или
$ python -c 'import string, sys; print(string.Template(open("template.txt").read()).substitute({"X":sys.argv[1]}))' "A"
Здесь
$X
- это заполнитель в шаблоне, а{"X":"A"}
- это отображение заполнителя в значение. В коде python мы читаем текст шаблона из файла, создаем шаблон из него, а затем заменяем заполнитель аргументом командной строки.В качестве альтернативы вы можете использовать ERB Ruby, если Ruby установлен на вашем компьютере.
$ echo "before <%= ENV['X'] %> after" > template.txt $ X=A erb template.txt before A after
Здесь
<%= ENV['X'] %>
является заполнителем.ENV['X']
считывает значение из переменная окружения.X=A
устанавливает переменную окружения в нужное значение.