Разворачивание скриптов

Часто бывает нужно развернуть на удаленный хост (управляемый при помощи chef) какие-то скрипты. Это не проблема, но не менее часто в этих скриптах бывают нужны привязки конкретно к этому хосту. Можно, конечно, реализовать обработку параметров командной строки или загрузку данных из конфига, но первое добавляет кучу кода в скрипт и часто неудобно само по себе (нам нужно будет передать при каждом запуске скрипта, скажем, с пяток некоротких параметров, причем каждый раз одинаковых), а загрузка данных из конфига неудобна тем, что приходится обрабатывать случаи, когда конфиг не найден, какие-то параметры не задали и т.д., что тоже не всегда оправдано.

К примеру, допустим, шеф у нас кладет на хост такой скрипт:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh

usage(){
 echo "Usage: $(basename "$0") SITE"
 exit 1
}

SITE="$1"

[ -z "${SITE}" ] && usage

mkdir "/var/www/${SITE}"
cat /etc/sitecfg/site.template | sed "s,@NAME@,${SITE},g" > "/etc/nginx/sites-available/${SITE}"

В этом скрипте хочется выделить в отдельные переменные несколько частей:

  • путь к каталогам с сайтами (/var/www)
  • имя темплейта (/etc/sitecfg/site.template)
  • путь, куда мы кладем обработанный темплейт (/etc/nginx/sites-available)
  • возможно, еще строку замены (s,@NAME@,${SITE},g)

Ясно, что все эти переменные передавать через командную строку не будешь, как не будешь и создавать отдельный конфиг для их хранения. При этом, для них лучше задать именно переменные, т.к., например, мы можем решить хранить сайты не в /var/www, а в /var/www/sites, назвать темплейт более внятным именем и положить в более правильное место и т.д.

Чтобы решить эту задачу, мы пишем скрипт как обычно, но в виде ERB-шаблона. Все нужные нам параметры придут от Chef-а. Первое желание написать его так:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh

usage(){
 echo "Usage: $(basename "$0") SITE"
 exit 1
}

SITE="$1"

[ -z "${SITE}" ] && usage

mkdir "<%= @sites_path %>/${SITE}"
cat "<%= @site_template %>" | sed "<%= @subst_string %> > "<%= @site_cfg_path %>/${SITE}"

Казалось бы, все нормально, однако легко заметить, что такие конструкции как минимум, нелегко читать, а значит легко допустить опечатку. Попробуйте найти, в каком месте я здесь забыл кавычку.

Перепишем таким образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh

# Generated by Chef for <%= node['fqdn'] %>

SITES_PATH="<%= @sites_path %>"
SITE_TEMPLATE="<%= @site_template %>"
SUBST_STRING="<%= @subst_string %>" 
SITE_CFG_PATH="<%= @site_cfg_path %>"

usage(){
 echo "Usage: $(basename "$0") SITE"
 exit 1
}

SITE="$1"

[ -z "${SITE}" ] && usage

mkdir "${SITES_PATH}/${SITE}"
cat "${SITE_TEMPLATE}" | sed "${SUBST_STRING}" > "${SITE_CFG_PATH}/${SITE}"

В результате получим довольно аккуратный скрипт, который легко читать и отлаживать.

Comments