Возможно ли на bash отрендерить какой-нибудь шаблон? Например, как в ansible? Конечно возможно! Сейчас покажу.



Давай возьмем огрызок конфига nginx и сделаем из него шаблон под разное окружение. У меня будет 2 сервера, естественно production и до кучи возьмем stage.



Создаем шаблон: nginx.tpl



user ${nginx_user};

worker_processes auto;

pid ${pid_path};

include /etc/nginx/modules/*.conf



Всё то, что нужно отрендерить, располагаем в ${параметр}.



Создаем скрипт с логикой:



>> nginx_gen.sh && chmod +x nginx_gen.sh



Символы «>>» означают - создать новый файл. А чмодиком делаем файл покорным и исполняемым.



Еще есть фича с созданием файла через touch nginx_gen.sh. Если запустить команду с touch повторно, то файл не перетрется, НО у него обновится дата и время создания. Иногда бывает полезно обновлять дату и время каким-нибудь файлам, которые выполняют роль флагов.



Так, поехали рендерить:



#!/bin/bash



function render {

export nginx_user=$1 pid_path=$2

cat nginx.tpl | envsubst > /etc/nginx/nginx.conf

}



if [[ $(hostname) == "production" ]]; then

nginx_user="www-data"

pid_path="/run/nginx.pid"

render $nginx_user $pid_path



else

nginx_user="nginx"

pid_path="/var/run/nginx.pid"

render $nginx_user $pid_path

fi



Разбираем портянку. Логика простая, если hostname равен production, то присваиваем одни переменные. Во всех других случаях присваиваем другие переменные.



Далее вызываем функцию render и передаем в нее nginx_user и pid_path. Функция render всё это дело экспортирует в переменные окружения, а затем с помощью envsubst заменяет их в шаблоне. Готовый конфиг сразу попадает в папку с nginx. Охуенно! Кайф!



envsubst - заменяет переменную окружения новым значением в формате строки оболочки командной строки. Переменные могут быть заменены в формате ${var} или $var



Если у тебя много переменных, то можешь их разом экспортировать через цикл. В предыдущих постах у меня где-то есть примеры таких циклов.



Собственно на этом можно и заканчивать. В 99% случаев все используют какой-то вонючий perl, sed, eval и т.п. Но решение с envsubst намного гибче и элегантнее.



Есть еще вариант с Heredoc. Heredoc-синтаксис — способ определения строковых переменных в исходном коде программ.



Пример скрипта, делает то же самое. Логику добавлять не стал:



#!/bin/bash



nginx_user="www-data"

pid_path="/var/run/nginx.pid"



cat > /etc/nginx/nginx.conf << EOF

user ${nginx_user};

worker_processes auto;

pid ${pid_path};

include /etc/nginx/modules-enabled/*.conf;

EOF



Отрендерится как нужно, но мне все же ближе вариант с envsubst. Нагляднее чтоли. Выбор лишь за тобой, на каком велосипеде кататься. Вот такие пироги. Ладно, побежал я дальше работу работать. Будьте здоровы! Увидимся!



tags: #linux #bash



💩 @bashdays