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

Источник: оригинал в Telegram

Давай возьмем огрызок конфига 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

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

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Собственно на этом можно и заканчивать. В 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. Нагляднее что ли. Выбор лишь за тобой, на каком велосипеде кататься. Вот такие пироги. Ладно, побежал я дальше работу работать. Будьте здоровы! Увидимся!