Bash скрипт создания виртуальных хостов Apache и Nginx

1

Вчера опубликовал статью о своем опыте настройки VPS. Обещал, что как только появится время, напишу пару баш скриптов, которые автоматизируют часть рутинной работы и сведут количество действий, выполняемых руками, к разумному минимуму.

Я напряг все имеющиеся извилины, откопал в аналах своей памяти скромные познания bash скриптинга и, потратив несколько часов, написал скромное приложение, которое упрощает и ускоряет процесс создания виртуальных хостов для Apache и Nginx.

Чтобы скрипт был хоть сколько-нибудь интересен не только мне и имел минимум привязки к среде, где он будет запускаться, я постарался вынести все пути и прочее в блок конфига, сохранив их в переменные. Тем не менее, я не рекомендую бездумно использовать его. Хотя бы глазами пробегитесь по коду, чтобы понимать, подойдет ли он вам «из коробки» (я сомневаюсь, если честно). Всякую ответственность за последствия, которые могут приключиться с вами после использования данного скрипта, само собой, я снимаю :) Все на свой страх и риск, как говорится. Но поломаться ничего не должно. Скрипт ничего не удаляет, не вносит изменений ни в какие файлы. Он может только намусорить…

Ниже код скрипта и некоторые комментарии к блоку конфига и способам использования.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#!/bin/bash
 
####### CONFIG START  ########
 
OWNER_NAME='username' # Пользователь, которому будет принадлежать директория вирт. хоста 
OWNER_GROUP='username' # Группа, которой будет принадлежать директория вирт. хоста 
HOME_WWW=~username/www # Домашняя директория для вирт. хостов 
HOST_DIRS=('backup' 'logs' 'public_html') 
SERVER_IP='127.0.0.1' # IP адрес сервера
 
WHEREIS_APACHE=/etc/apache2
WHEREIS_NGINX=/etc/nginx
 
APACHE_HOSTS_DIR=$WHEREIS_APACHE'/sites-available'
NGINX_HOSTS_DIR=$WHEREIS_NGINX'/sites-available'
NGINX_HOSTS_ENABLED=$WHEREIS_NGINX'/sites-enabled'
 
######## CONFIG END ##########
 
# COLORS
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_NORMAL="echo -en \\033[0;39m"
SETCOLOR_NOTICE="echo -en \\033[1;33;40m"
 
# FUNCTIONS
 
function restart_servers {
    echo 'Перезапускаем Apache'
    /etc/init.d/apache2 reload
 
    echo 'Перезапускаем Nginx'
    /etc/init.d/nginx reload
 
    return 1
}
 
function error_config {
    $SETCOLOR_FAILURE
    echo "$(tput hpa $(tput cols))$(tput cub 6)[Fail]"
    echo '[CONFIG ERROR]: '$1
    $SETCOLOR_NORMAL
 
    exit
}
 
function error_force_exec {
    $SETCOLOR_FAILURE
    echo "$(tput hpa $(tput cols))$(tput cub 6)[Fail]"
    echo -n '[FORCE EXEC ERROR]: '
 
    if [ -z "$1" ]; then
	echo 'Скрипт не может корректно выполнить все процедуры в автоматическом режиме'
    else
	echo $1
    fi
 
    $SETCOLOR_NORMAL
 
    exit
}
 
function error_failure {
    $SETCOLOR_FAILURE
    echo "$(tput hpa $(tput cols))$(tput cub 6)[Fail]"
    echo '[ERROR]: '$1
    $SETCOLOR_NORMAL
 
    exit
}
 
function error_notice {
    $SETCOLOR_NOTICE
    echo '[NOTICE]: '$1
    $SETCOLOR_NORMAL
 
    return 1
}
 
# Если запущен с ключем -f, значит задаем пользователю минимум вопросов 
# Игнорируются вопросы: 
# - имя директории виртуального хоста 
# - вопрос о перезапуске серверров (будут перезапущены)
 
if [ "$1" == "-f" ]; then
    force_execution=true
else
    force_execution=false
fi
 
echo
 
$SETCOLOR_NORMAL
 
if [ -d $HOME_WWW ]; then
    cd $HOME_WWW
else
    error_config "Директория $HOME_WWW не существует"
fi
 
# Запрашивает имя домена, пока не будет введено
function get_domain_name {
    echo -n "Имя домена: "
    read domain_name
 
    # Если ничего не было введено
    if [ -z $domain_name ]; then
	$SETCOLOR_FAILURE
	echo "Вы не ввели имя домена"
	$SETCOLOR_NORMAL
	get_domain_name
    else
	return 1
    fi
}
 
# Запрашивает имя директории для виртуального хоста или предлагает создать автоматически 
# проверяет его на существование
function get_host_dir {
    echo -n "Имя директории хоста: "
    read host_dir
 
    # Если ничего не было введено
    if [ -z $host_dir ]; then
	$SETCOLOR_NOTICE
	echo -n "Вы не ввели имя директории хоста. Создать автоматически? [Н/д]? "
	$SETCOLOR_NORMAL
 
	read answer
 
	    case "$answer" in
	    Y|y|д|Д)
		host_dir=${domain_name//\./_}
		host_dir=${host_dir//\-/}
 
		if [ -d ${HOME_WWW}'/'${host_dir} ]; then
		    error_notice "Автоматический выбор имени директории невозможен. Задайте его самостоятельно"
		    get_host_dir
		else
		    error_notice "Директория хоста будет создана автоматически: $host_dir"
		fi
		return 1
		;;
	    N|n|о|О) get_host_dir
		;;
	    *) get_host_dir
		;;
	    esac
	get_host_dir
    else
	return 1
    fi
}
 
get_domain_name
 
if $force_execution; then
    host_dir=${domain_name//\./_}
 
    if [ -d ${HOME_WWW}'/'${host_dir} ]; then
	error_force_exec
    fi
else
    get_host_dir
fi
 
# Проверяем пути апача из конфига
if [ -d $APACHE_HOSTS_DIR ]; then
    if [ -a $APACHE_HOSTS_DIR'/'$domain_name ]; then
	error_failure "Виртуальный хост $domain_name уже существует для Apache"
    fi
else
    error_config "Директория $APACHE_HOSTS_DIR не существует"
fi
 
# Проверяем пути nginx из конфига
if [ -d $NGINX_HOSTS_DIR ]; then
    if [ -a $NGINX_HOSTS_DIR'/'$domain_name ]; then
        error_failure "Виртуальный хост $domain_name уже существует Nginx"
    fi
else
    error_config "Директория $NGINX_HOSTS_DIR не существует"
fi
 
echo "Домен: $domain_name"
 
# Создаем директории виртуального хоста
host_dir_path=${HOME_WWW}'/'${host_dir}
echo "Создаем директории виртуального хоста:"
 
mkdir $host_dir_path
 
for dir_name in ${HOST_DIRS[@]}; do
	mkdir $host_dir_path'/'$dir_name
	echo -e "\t $host_dir_path/$dir_name"
done
 
touch ${host_dir_path}'/public_html/index.html'
 
# Рекурсивно проставляем права
chown -R $OWNER_NAME:$OWNER_GROUP $host_dir_path
 
apache_template="<VirtualHost 127.0.0.1:8080>
      ServerAdmin webmaster@$domain_name
      ServerName $domain_name
      ServerAlias www.$domain_name
      DocumentRoot $HOME_WWW/$host_dir/public_html
 
      ScriptAlias /cgi-bin/ $HOME_WWW/$host_dir/public_html/cgi-bin/
      ErrorLog $HOME_WWW/$host_dir/logs/apache.error.log
      LogLevel warn
      CustomLog $HOME_WWW/$host_dir/logs/apache.access.log combined
</VirtualHost>"
 
# Создаем конфиг виртуального хоста apache
echo 'Создаем конфиг виртуального хоста apache:'
touch ${APACHE_HOSTS_DIR}'/'${domain_name}
echo -e "\t"${APACHE_HOSTS_DIR}'/'${domain_name}
 
temp_ifs=$IFS
IFS=
echo $apache_template > ${APACHE_HOSTS_DIR}'/'$domain_name
IFS=$temp_ifs
 
# создаем симлинк
a2ensite $domain_name
 
nginx_template="server {
      listen $SERVER_IP:80;
 
      server_name $domain_name www.$domain_name;
      access_log  $HOME_WWW/$host_dir/logs/nginx.access.log;
 
      location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar)$ {
            root /home/omm/www/$host_dir/public_html;
      }
 
 
      location / {
            proxy_pass http://backend;
            proxy_redirect off;
            proxy_set_header Host \$host;
            proxy_set_header X-Real-IP \$remote_addr;
 
            charset utf-8;
            index index.html;
            root $HOME_WWW/$host_dir/public_html;
      }
}"
 
 
# Создаем конфиг виртуального хоста nginx
echo 'Создаем конфиг виртуального хоста nginx:'
touch ${NGINX_HOSTS_DIR}'/'${domain_name}
echo -e "\t"${NGINX_HOSTS_DIR}'/'${domain_name}
 
temp_ifs=$IFS
IFS=
echo $nginx_template > ${NGINX_HOSTS_DIR}'/'$domain_name
IFS=$temp_ifs
 
# создаем симлинк
ln -s $NGINX_HOSTS_DIR'/'$domain_name $NGINX_HOSTS_ENABLED'/'$domain_name
 
# Перезапускаем сервера
if $force_execution; then
    restart_servers
else
    echo -n 'Перезапустить Apache и Nginx? [Д/н] '
    read restart_answer
 
    case "$restart_answer" in
	Y|y|д|Д)
	    restart_servers
	;;
	*)
	    echo 'Apache и Nginx не были перезагружены'
	;;
    esac
 
fi
 
$SETCOLOR_SUCCESS
echo "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
$SETCOLOR_NORMAL

Конфигурирование скрипта

В скрипте есть комментарии, но опишу переменные настройки еще раз.

OWNER_NAME – имя системного пользователя, которому будут принаджелать директории и файлы, создаваемые скриптом для виртуального хоста.

OWNER_GROUP – системная группа, которой будут принаджелать директории и файлы, создаваемые скриптом для виртуального хоста.

HOME_WWW – внутри этой директории будет создана директория виртуального хоста.

HOST_DIRS – директории виртуального хоста, которые будут созданы. По-умолчанию сюда вписана директория для логов apache и nginx, директория для бэкапов и директория, которая будет доступна по http протоколу, собственно, куда и нужно будет класть все файлы вашего сайта.

SERVER_IP – ip адрес вашего сервера. Прописывается в конфигах nginx.

WHEREIS_APACHE – директория установки Apache. Относительно нее будут искаться конфиги виртуальных хостов и прочее.

WHEREIS_NGINX – директория установки Nginx. Относительно нее будут искаться конфиги виртуальных хостов и прочее.

APACHE_HOSTS_DIR – директория, где Apache хранит конфиги для каждого отдельного виртуального хоста. Обычно это sites-available.

NGINX_HOSTS_DIR – директория, где Nginx хранит конфиги для каждого отдельного виртуального хоста. Обычно это sites-available.

NGINX_HOSTS_ENABLED – директория, где хранятся симлинки на конфиги виртуального хоста Nginx. В nginx нет утилиты подобной a2ensite, поэтому нужно знать, куда создать ссылку самим. Обычно данная директория называется sites-enabled.

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

В скрипте есть еще две переменных, которые объявлены почти в конце листинга: apache_template и nginx_template. В них хранятся шаблоны для виртуальных хостов. Хотя бы посмотрите, что в них описано, чтобы быть уверенными в том, что конфиги имеют именно тот вид, который вам требуется.

Работа со скриптом

Скрипт может работать в двух режимах.

Простой запуск – запускаете скрипт и отвечаете на его вопросы. Он потребует ввести:

  • имя домена, для которого создаются конфиги;
  • имя директории виртуального хоста;
  • спросит перезагрузить ли сервера, после того, как конфиги будут созданы

Если не задать скрипту имя директории виртуального хоста, то он создает ее автоматически. От перезагрузки серверов можно отказаться. Это удобно, когда вы планируете создать несколько виртуальных хостов подряд и нет смысла каждый раз заставлять Nginx и Apache делать reload (при reload создается избыточная нагрузка на процессор и потребляется больше памяти. Лучше сделать это один раз, когда все хосты будут добавлены).

Форсированный запуск – это типа автоматического режима. Скрипт задает только один вопрос – о имени домена. Все остальное он делает сам, в том числе перезагружает Nginx и Apache. При этом, если в ходе проверок скрипт выяснит, что выполнить какие-то операции он не сможет, то работа прекратится. Но учтите, что никаких подробных сообщений о проблеме не будет. Скрипт просто скажет, что он не может отработать в автоматическом режиме (скорее всего, конфликты с путями).

Для вызова скрипта в форсированом режиме необходимо запустить его с параметром –f

bash script_name.sh -f

На баше я пишу раз в сотню лет, так что, уж не обессудьте.

Linux

Комментарии (1 комментарий)

  1. Спасибо, друг! Прям спас от мучительной смерти за тоннами манов!

Оставить комментарий