Сборка nginx: CentOS 6.8, документы и грабли

в 14:15, , рубрики: centos 6, install, nginx, source code

Недолюбливаю пакеты redhat. Они небезопасны: любой пакет можно изучить заранее; они не дают должного контроля, в отличие от сборки, поэтому предпочитаю последнюю. Однако есть в пакетах и кое-что хорошее, о чём скажу ниже. Кажется, собрал из исходников сервер – «молодец», статья зачем?

Документация пока упускает существенные детали, а статьи с рекомендациями, как лучше, во-первых, разрознены и, как правило, не цельны, а во-вторых отсылают к далёким источникам, тогда как на самом деле всё под рукой. Я предлагаю решение. Вместе с тем, покажу несколько удобных, на мой взгляд, вспомогательных функций bash для сборки как таковой. Кроме того, сборочный скрипт будет «из коробки» прятать версию и имя сервера, делая это, конечно же, на уровне исходников, а не директивы server_tokens, так что не нужно никакой коммерческой подписки. Интересно?

Начну с документации. Конечно же, соответствующие правки будут предложены сообществу nginx. Вот такой скрипт у нас получится, если ей верить:

#!/bin/bash
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.39.tar.gz
tar -zxf pcre-8.39.tar.gz
cd pcre-8.39
./configure
make
sudo make install

wget http://zlib.net/zlib-1.2.8.tar.gz
tar -zxf zlib-1.2.8.tar.gz
cd zlib-1.2.8
./configure
make
sudo make install

wget http://www.openssl.org/source/openssl-1.0.2f.tar.gz
tar -zxf openssl-1.0.2f.tar.gz
cd openssl-1.0.2f

Конфигуратор OpenSSL на самом деле называется config, а здесь:

./configure darwin64-x86_64-cc --prefix=/usr
make
sudo make install

wget http://nginx.org/download/nginx-1.10.2.tar.gz
tar zxf nginx-1.10.2.tar.gz
cd nginx-1.10.2

./configure --sbin-path=/usr/local/nginx/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --with-pcre=../pcre-8.39 --with-zlib=../zlib-1.2.8 --with-http_ssl_module --with-stream --with-mail=dynamic --add-module=/usr/build/nginx-rtmp-module --add-dynamic-module=/usr/build/3party_module

make
sudo make install
sudo nginx

Во-первых, мне не нравится рутина: скачать исходники, распаковать, перейти в их папку. В несколько команд. Предлагаю пригодную в подавляющем большинстве случаев функцию bash, работающую с 7z и ещё одной функцией, возвращающей корень архива.

#!/bin/bash
set -x
sudo yum -y install p7zip wget tidy util-linux openssl-devel

Возвращает корень архива:

arroot () {
7z l "$1" | grep '^[0-9][0-9][0-9][0-9]' | head -n1  | gawk '{print $NF}'
}

Распаковывает архивы и переходит к исходникам. При желании домашняя директория меняется на /usr/local/src:

gotosrc () {
cd "$HOME"
echo "$1" > /var/tmp/gawk.temp
arname=$(gawk -F/ '{print $NF}' /var/tmp/gawk.temp)

	if ! test -f "$arname"; then {
	wget -P "$PWD" "$1"
	}
	fi

7z x "$arname"

	if test -f $(arroot "$arname"); then {
	7z x $(arroot "$arname")
	srcfold=$( arroot $(arroot "$arname") )
	} else {
	srcfold=$( arroot "$arname" )
	} 
	fi

cd "$srcfold"; ls -la
}

Короткая обёртка установки прав выполнения configure:

setconfex () {
	if ! test -x configure; then {
	sudo chmod +x configure
	}
	fi
}

Дальше – инструкции make. В них часто забывают о параметрe make -jn, n – число рабочих процессов; работает не всегда, но в многоядерной современности значительно ускоряет make. Для использования узнаём число ядер процессора:

getnumcores () {
echo $(( $(lscpu -p=core | wc -l) - 4  ))
}
# ...
make -j$(getnumcores); sudo make -j$(getnumcores) install

Она же пригодится для конфигурирования директивы количества рабочих процессов nginx. А эта функция возвращает ссылку на новейший архив исходников стабильной ветки с официального сайта:

getlatestlink_nginx () {
# tidy нужен для удобной работы grep
curl "http://nginx.org/en/download.html" | tidy -imc | grep "/download/nginx" | gawk -F'"' '{print $2}' > /var/tmp/temp.file.gawk
branchnum=$( head -n1 /var/tmp/temp.file.gawk | gawk -F'.' '{print $2}' )

	if [ "$(( $branchnum % 2 ))" = "1" ]; then {
	latestlink="https://nginx.org"$( grep "$(($branchnum - 1))" /var/tmp/temp.file.gawk | head -n1 )
	echo "$latestlink"
	} 
	fi
}

Почему не git clone? Архивы проще, надёжней, да и github всегда предлагает zip-архив.

gotosrc $( getlatestlink_nginx )

Теперь, когда мы скачали и собрали зависимости (ссылка на весь код) и оказались в исходниках nginx, можно прятать его версию, просто оставив запрошенные этой функцией строки пустыми:

hidengxver () {
read -r -p "Your own http_server_string for safety: " http_server_string
first_string="static char ngx_http_server_string[] = "Server: nginx" CRLF;"
second_string="static char ngx_http_server_string[] = "$http_server_string" CRLF;"
sed -ire "s/$first_string/$second_string/g" src/http/ngx_http_header_filter_module.c
	
read -r -p "Your own NGINX_VER const: " nginx_ver
third_string="#define NGINX_VER          "nginx/" NGINX_VERSION"
forth_string="#define NGINX_VER          "$nginx_ver" NGINX_VERSION"
sed -ire "s/$third_string/$forth_string/g" src/core/nginx.h
	
real_nginx_version=$( grep '#define NGINX_VERSION' src/core/nginx.h | gawk -F'"' '{print $2}' )
read -r -p "Your own NGINX_VERSION const: " new_nginx_version
fifth_string="#define NGINX_VERSION      "$real_nginx_version""
sixth_string="#define NGINX_VERSION      "$new_nginx_version""
sed -ire "s/$fifth_string/$sixth_string/g" src/core/nginx.h 
}

Ловкость sed и никакой коммерции. Команда nginx вряд ли скажет спасибо, но я благодарю её за красивый структурированный код и пользователя StackOverflow Martin M. за его пост – основу функции.
И самое интересное. Что хорошо в пакетах? Конечно же, дополнительные скрипты. И если без команды service nginx start и подобных можно обойтись, то без ротации логов… Сами понимаете. Напишем распаковывающую пакет функцию и разложим нужные файлы по местам.

gotorpm () {
cd "$HOME"
echo "$1" > /var/tmp/gawk.temp
rpmname=$(gawk -F/ '{print $NF}' /var/tmp/gawk.temp)

	if ! test -f "$rpmname"; then {
	wget -P "$PWD" "$1"
	}
	fi

7z x "$rpmname"
rpmname_size=${#rpmname}
rpmfold=${rpmname:0:($rpmname_size-4)}
mkdir "$rpmfold"; mv "$rpmfold"".cpio" "$rpmfold"
cd "$rpmfold"
7z x "$rpmfold"".cpio"
ls -la
}

Дублирование кода – зло и можно лучше, но функция ясна и делает дело.

Обращаю внимание: пакетные файлы рассчитаны на префикс /usr, с которым при установке из исходников образуется бардак, потому оставим /usr/local/nginx и заменим пару строк в пакете до копирования в систему:

modify_nginx_init () {
first_init_string="NGINX=/usr/sbin/nginx"
second_init_string="NGINX=/usr/local/nginx/sbin/nginx"
sudo sed -ire "s/$first_init_string/$second_init_string/g" etc/sysconfig/nginx

third_init_string="nginx=${NGINX-/usr/sbin/nginx}"
forth_init_string="nginx=${NGINX-/usr/local/nginx/sbin/nginx}"
sudo sed -ire "s/$third_init_string/$forth_init_string/g" etc/rc.d/init.d/nginx
}

Лично мне при знакомстве с Линукс и командами user{add,mod.del} чисто психологически не хватило ещё двух:

userlist () {
sudo gawk -F: '{print $1}' /etc/passwd | sort -g
}

userex () {
	if [ "$( userlist | grep "$1" )" = "$1"  ]; then {
	return 0 
	} 
	else { 
	return 1 
	} 
	fi
}

И, наконец, функция установки с учётом изложенного:

install_nginx () {
nginx_install_prefix="/usr/local/nginx"
#install pcre
gotosrc "ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.39.tar.gz"
setconfex
./configure --prefix=$nginx_install_prefix
make -j$(getnumcores)
sudo make -j$(getnumcores) install
#instaall zlib
gotosrc "http://zlib.net/zlib-1.2.8.tar.gz"
setconfex
./configure --prefix=$nginx_install_prefix
make -j$(getnumcores)
sudo make -j$(getnumcores) install
#install nginx
gotosrc $(getlatestlink_nginx)
setconfex
hidengxver

Параметры configure из пакета с небольшими изменениями:

./configure --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-threads --with-stream --with-stream_ssl_module --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-http_v2_module --with-ipv6 --with-pcre=../pcre-8.39 --with-zlib=../zlib-1.2.8
make -j$(getnumcores); sudo make -j$(getnumcores) install

gotorpm "https://nginx.org/packages/centos/6/x86_64/RPMS/nginx-1.10.2-1.el6.ngx.x86_64.rpm" 
modify_nginx_init
sudo cp etc/sysconfig/nginx /etc/sysconfig/nginx
sudo cp etc/logrotate.d/nginx /etc/logrotate.d/nginx
sudo cp etc/rc.d/init.d/nginx /etc/rc.d/init.d/nginx

Да, сервер при запуске жалуется на отсутствие одной из папок, несмотря на её указание конфигуратору. Исправляем:

if ! test -d /var/cache/nginx/client_temp; then {
sudo mkdir -p /var/cache/nginx/client_temp
}
fi

Конфигуратором не создаётся пользователь nginx, делаем сами:

if ! userex "nginx"; then {
sudo useradd --home-dir /var/cache/nginx "nginx"
}
fi

Добавляем сервис:

sudo chmod +x /etc/rc.d/init.d/nginx
sudo chkconfig --add nginx

Если есть другая копия и она не остановлена или мертва:

if [ -z "$( sudo service nginx status | grep "stopped"  )" ]; then {
sudo service nginx stop
}
fi
sudo service nginx start; sudo chkconfig nginx on
sudo service nginx status

Чтобы Engine X не послал на Forbidden:

sudo chown -R "nginx" "$nginx_install_prefix""/html"
curl localhost
}

install_nginx

Ещё раз полный код.

Спасибо за внимание. Конструктивная критика, предложения и замечания приветствуются.

Автор: stranger777

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js