четверг, 28 февраля 2008 г.

Виртуальные apache домены автоматом

Есть у меня привычка, для каждого сайта создавать отдельный локальный "домен". И было это легко делать в винде, ибо там есть денвер. Он на лету генерировал apache-кофиги и прописывал хосты в hosts в зависимости от структуры каталогов.

Например, из следующего дерева каталогов получаются домены dom1, www.dom1, sub1.dom1, sub2.dom1, another.dom, www.another.dom, причём dom1=www.dom1, another.dom=www.another.dom

dom1/
  sub1/
  sub2/
  www/
another.dom/
  www/

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


# echo 'Include /etc/apache2/vhosts.d/autogenerated/*.conf' > /etc/apache2/vhosts.d/autogenerated.conf
# mkdir /etc/apache2/vhosts.d/autogenerated
# touch /usr/local/sbin/host_generator && chmod +x /usr/local/sbin/host_generator

Файл /usr/local/sbin/host_generator приведен ниже.

Перед стартом, проверьте свой /etc/hosts и запишите домены, отвечающие узлу 127.0.0.1 в DEFAULT_LOCALHOSTS. Также поправьте APACHE_HOME_DIR, если путь к файлам сервера отличается от "/var/www/".

По умолчанию, скрипт рассматривает все подкаталоги как поддомены. Это поведение можно изменить редактированием файлов ACCEPTED_HOSTS и FORBIDDEN_HOSTS. По умолчанию FORBIDDEN_HOSTS пуст, а ACCEPTED_HOSTS содерижит единственную всё-разрешающую запись: */* . Взять скрипт отдельным файлом можно здесь

/usr/local/sbin/host_generator

#!/bin/bash

###### НАЧАЛО КОНФИГУРАЦИИ
# Будут добавленны все разрешённые, не запрещённые хосты
ACCEPTED_HOSTS="/root/.hag_accepted.conf"
FORBIDDEN_HOSTS="/root/.hag_forbidden.conf"
APACHE_HOME_DIR="/var/www/"
APACHE_CONFS_DIR="/etc/apache2/vhosts.d/autogenerated/"
DEFAULT_LOCALHOSTS="localhost"
BE_VERBOSE=false
###### КОНЕЦ КОНФИГУРАЦИИ



if [ "$UID" -ne 0 ]
then 
 echo "Superuser rights is required"
 exit 2
fi

genApacheConf(){
 if [[ "$2" = "www" ]]
 then 
  full_domain=$1
 else
  full_domain=$2.$1
 fi 
 host_root="${APACHE_HOME_DIR}$1/$2"
 echo -e "# Host $1/$2 :"
 echo -e "<VirtualHost *:80>"
 echo -e "\tServerName \"$full_domain\""
 echo -e "\tServerAlias \"$full_domain\" \"www.$full_domain\""
 echo -e "\tDocumentRoot \"${host_root}\""

 echo -e "\t<Directory \"${host_root}\">"
 echo -e "\t\tOptions Indexes FollowSymLinks"
 echo -e "\t\tAllowOverride All"
 echo -e "\t\tOrder allow,deny"
 echo -e "\t\tAllow from all"
 echo -e "\t</Directory>"
 echo "</VirtualHost>"
 echo
}


# Очищение $APACHE_CONFS_DIR
find "${APACHE_CONFS_DIR}" -mindepth 1 -exec rm -v \{\} > /dev/null \; || { echo "(EE) При очистке ${APACHE_CONFS_DIR} произошла ошибка"; exit 1; }


# Читаем настройки
if [ ! -e $ACCEPTED_HOSTS ]
then
 [ $BE_VERBOSE = true ] && echo "Создаётся файл '$ACCEPTED_HOSTS'"
 echo '*/*' > $ACCEPTED_HOSTS || { echo "(EE) Невозможно создать $ACCEPTED_HOSTS"; exit 1; }
fi
if [ ! -e $FORBIDDEN_HOSTS ]
then
 [ $BE_VERBOSE = true ] && echo "Создаётся файл '$FORBIDDEN_HOSTS'"
 touch $FORBIDDEN_HOSTS || { echo "(EE) Невозможно создать $FORBIDDEN_HOSTS"; exit 1; }
fi


set -f
accepted_hosts=( $(cat $ACCEPTED_HOSTS))
forbidden_hosts=( $(cat $FORBIDDEN_HOSTS) )

found_doms=( )
found_sub_doms=( )
hosts=$(ls $APACHE_HOME_DIR)
hosts_to_attach=""
for host in $hosts
do
 subdoms=$(find ${APACHE_HOME_DIR}${host}/ -maxdepth 1  -mindepth 1 -type d -or -type l | grep -Po "[^/]+$")
 has_accpepted_doms=false
 for sd in ${subdoms[@]}
 do
  accepted=false
  [ $BE_VERBOSE = true ] && echo "-------- $host/$sd"
  for pattern in ${accepted_hosts[@]}
  do
   echo "$host/$sd" | grep -qP "^${pattern//\*/[^/]*}\$"
   if [ $? = 0 ] 
   then
    [ $BE_VERBOSE = true ] && echo "--- Путь '$host/$sd' разрешён правилом $pattern"
    accepted=true
    break
   fi
  done
  if [ $accepted != true ]; then continue; fi;
  forbidden=false
  for pattern in ${forbidden_hosts[@]}
  do
   echo "$host/$sd" | grep -qP "^${pattern//\*/[^/]*}\$"
   if [ $? = 0 ] 
   then
    [ $BE_VERBOSE = true ] && echo "--- Путь '$host/$sd' запрещён правилом $pattern"
    accepted=true
    forbidden=true
    break
   fi
  done
  if [ $forbidden != true ]
  then
   has_accpepted_doms=true
   found_sub_doms=( ${found_sub_doms[@]} "$host/$sd" )
  fi
 done
 if [ $has_accpepted_doms = true ]
 then
  found_doms=( ${found_doms[@]} "$host" )
 fi
done

[ $BE_VERBOSE = true ] && echo
hosts_to_attach=""
for dom in ${found_doms[@]}
do
 [ $BE_VERBOSE = true ] && echo "----> Добавляем домен $dom"
  hosts_to_attach+=" $dom"
 for sd_full in ${found_sub_doms[@]}
 do
  host=${sd_full/\/*/}
  if [ "$host" != "$dom" ]; then continue; fi
  sd=${sd_full/*\//}
  [ $BE_VERBOSE = true ] && echo "----> Добавляем поддомен $sd.$host"
   hosts_to_attach+=" $sd.$host"
   [ $BE_VERBOSE = true ] && echo "------> Записываем apache конфигурацию в файл ${APACHE_CONFS_DIR}${host}_${sd}.conf"
   genApacheConf $host $sd > ${APACHE_CONFS_DIR}${host}_${sd}.conf || { echo "EE ------> Ошибка при записи в ${APACHE_CONFS_DIR}${host}_${sd}.conf!"; exit 1; }
 done
done
[ $BE_VERBOSE = true ] && echo
 
echo "Найдены поддомены ${found_sub_doms[@]}"

[ $BE_VERBOSE = true ] && { echo; echo "> Обновляем /etc/hosts"; }
comment_string="# Autogenerated by $0, don't edit manualy"
resulted_string="${comment_string}\n127.0.0.1 ${DEFAULT_LOCALHOSTS}${hosts_to_attach}\n"
new_hosts=$(awk -v ress="${resulted_string}" -v coms="${comment_string}" 'BEGIN {n=1}; /^127.0.0.1/ {if (n == 1) printf ress; else print "#",$0 ; n = n + 1}; !/^127.0.0.1/ {if ($0!=coms) print};'  /etc/hosts)

{ echo "$new_hosts" > /etc/hosts; } || { echo "(EE) Невозможно записать в /etc/hosts"; exit 1; }

1 комментарий:

Анонимный комментирует...

давно искал подобное, попробуем))