Nginx skrypt do kompilacji

Marcin Kaciuba 29.04.2015

Po co administrator pisze skrypty? Po to by mieć więcej czasu. A na co? Na pisanie skryptów. Tym sucharem chciałbym zacząć post na temat skryptu, który powstał z potrzeby dodania 1 modułu do nginxa..

 

Potrzebowałem dodać jedynie nginx_page_speed. Znalazłem paczkę  nginxa z tym modułem, ale miałem problem z zależnościami...więc postanowiłem skompilować sobie nginxa.  I dzięki temu napisałem wydaje mi nawet dobry skrypt do kompilacji binarki nginxa. Bezproblemu można dodać czy usunąć moduł. Plik na dole zawiera całą konfiguracje skryptu:

version: "1.8.0"
hooks:
    postdownload: ~
    postconfigure: ~

modules:
    ngx_devel_kit:
        source: 'https://github.com/simpl/ngx_devel_kit.git'
        version: 'tags/v0.2.19'
    nginx-upstream-fair:
        source: 'https://github.com/gnosek/nginx-upstream-fair.git'
        version: ~
    lua-nginx:
        source: 'https://github.com/openresty/lua-nginx-module.git'
        version: 'tags/v0.9.15 '
    lua-upstream-cache-nginx:
        source: 'https://github.com/cloudflare/lua-upstream-cache-nginx-module.git'
        version: 'tags/v0.1.1'
  
    nginx-upload-progress:
        source: 'https://github.com/masterzen/nginx-upload-progress-module/archive/v0.9.1.tar.gz'
    echo-nginx:
        source: 'https://github.com/openresty/echo-nginx-module.git'
        version: 'tags/v0.57'
    nginx-push-stream:
        source: 'https://github.com/wandenberg/nginx-push-stream-module.git'
        version: 'tags/0.4.1'
    headers-more-nginx:
        source: 'https://github.com/openresty/headers-more-nginx-module.git'
        version: 'tags/v0.25'
    ngx_cache_purge:
        source: 'https://github.com/FRiCKLE/ngx_cache_purge.git'
        version: 'tags/2.3'
    nginx-dav-ext:
        source: 'https://github.com/arut/nginx-dav-ext-module.git'
        version: 'tags/v0.0.3'
    ngx_http_substitutions_filter:
        source: 'https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git'
        version: 'tags/v0.6.4'
    ngx_pagespeed:
        source: 'https://github.com/pagespeed/ngx_pagespeed.git'
        version: 'tags/v1.9.32-3-beta'
        postdownload:
            - 'wget -nc https://dl.google.com/dl/page-speed/psol/1.9.32.3.tar.gz'
            - 'tar -xzvf 1.9.32.3.tar.gz'
    ngx-fancyindex:
        source: 'https://github.com/aperezdc/ngx-fancyindex.git'
        version: 'tags/v0.3.5'

configure:
    - with-ld-opt=-Wl,-L/usr/lib/,-z,relro
    - with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2  -I/usr/include/luajit-2.0/  -I/usr/include/uuid/'
    - with-http_ssl_module
    - prefix=/usr/share/nginx
    # flagi kompilacji- ...
install_deps:
    - libluajit-5.1-dev
    - liblua5.1-0
    - libluajit-5.1-common
    - redis-server
    - libhiredis-dev
    - liblua5
    - libpcre3
    - libpcre3-dev
    - libgd2-xpm
    - libgd2-xpm-dev
    - libgeoip-dev
    - openssl
    - libssl-dev
    - libperl-dev
    - lib64z1
    - uuid-dev

enviroment:
    LUAJIT_LIB: '/usr/lib/'
    LUAJIT_INC: '/usr/include/luajit-2.0/'

Objaśnienia:

  • version - wersja nginx do skompilowana
  • hooks - komendy wykonywane odpowiednio 
    • postdownload - po ściągnięciu źródła nginx
    • postconfigure - po wykonaniu polecenia configure
  • modules - lista modułów do ściągnięcia i skompilowania. Gdy link ma końcówkę git skrypt ma możliwość przełączenia się na tag lub branch. Tutaj jest też hook postdownload
  • configure - flagi do kompilacji nginx
  • install_deps - zależności do zainstalowania za pomocą apt-get
  • enviroment - zmienne środowiskowe przekazane do skryptów

Cały proces kompilacji odbywa się folderze /tmp/nginx.

Sam skrypt może nie jest najładniejszym kodem napisanym prze zemnie w pythonie, ale spełnia swoją funkcje co jest dla mnie najważniejsze:

#!/usr/bin/env python
import yaml
import os
import subprocess

config = yaml.load(open('./modules.yml'))
hooks = config['hooks']
env = os.environ
for key, value in config['enviroment'].iteritems():
    if value:
        env[key] = value


shell = lambda cmd: subprocess.call(cmd, shell=True, env = env)
base_path = '/tmp/'

def clone_repo(url, path, version):
    shell('git clone ' + url + ' ' + path)
    if version:
        shell('cd '+ path +' && git checkout ' + version)

def download(url, path):
    download_path = os.path.join(path, 'download')
    shell('mkdir -p ' + download_path)
    shell('wget -nc ' + url + ' -P ' +  download_path)

    if url.endswith('.tar.gz'):
        filename = url.split('/')
        filename = filename[len(filename) - 1]

        shell('tar zxf ' + os.path.join(download_path, filename) + ' -C ' + path)
        lst = [ name for name in os.listdir(path) if os.path.isdir(os.path.join(path, name)) and name[0] != '.' and name != 'download'  ]
        print(lst)
        return os.path.join(path, lst[0])
    return download_path


def prepare_modules(modules):
    modules_path = []
    for name, mod in modules.iteritems():
        path = os.path.join(base_path, name)
        if mod['source'].endswith('.git'):
            clone_repo(mod['source'], path, mod['version'])
        else:
            path = download(mod['source'], path)
        modules_path.append(path)
        if 'postdownload' in mod:
            for post in mod['postdownload']:
                shell('cd ' + path + ' && ' + post)
    return modules_path

def install_deps(deps):
    for dep in deps:
        shell('sudo apt-get install ' + dep)


def configure(args, modules):
    configure_args = ' --' + ' --'.join(args)
    for mod in modules:
        configure_args +=  ' --add-module=' + mod
    return configure_args

install_deps(config['install_deps'])
modules = prepare_modules(config['modules'])
configure_args = configure(config['configure'], modules)

nginx_path = download('http://nginx.org/download/nginx-' + config['version'] + '.tar.gz', os.path.join(base_path, 'nginx'))

print configure_args
shell('cd ' + nginx_path + ' && ./configure ' + configure_args)
if 'postconfigure' in hooks:
    if hooks['postconfigure']:
        for cmd in hooks['postconfigure']:
            cmd = cmd.replace('{{nginx_path}}', nginx_path)
            print(cmd)
            shell(cmd)
shell('cd ' + nginx_path + ' && make -j2')

Przygotowanie paczki deb

Gdy już nginx zostanie skompilowany mamy możliwość zbudowania paczki debianowskie za pomocą skryptu debpackage.sh. Przykładowe wywołanie:

./debpackage.sh /tmp/nginx/nginx-1.8.0 1.8.0

Pliki konfiguracyjne dla nginx znajdują się w folderze package. Trzeba zwrócić uwagę na to, że przy instalacji tak zbudowanej paczki zostają nadpisane wszystkie poniżej wyszczególnione pliki:

$ tree package 
package
├── etc
│   ├── default
│   │   └── nginx
│   ├── init.d
│   │   └── nginx
│   ├── logrotate.d
│   │   └── nginx
│   ├── nginx
│   │   ├── fastcgi.conf
│   │   ├── fastcgi_params
│   │   ├── koi-utf
│   │   ├── koi-win
│   │   ├── mime.types
│   │   ├── nginx.conf
│   │   ├── proxy_params
│   │   ├── scgi_params
│   │   ├── sites-available
│   │   │   └── default
│   │   ├── snippets
│   │   │   ├── fastcgi-php.conf
│   │   │   └── snakeoil.conf
│   │   ├── uwsgi_params
│   │   └── win-utf
│   └── ufw
│       └── applications.d
│           └── nginx
└── lib
    └── systemd
        └── system
            └── nginx.service

Po zaskoczeniu skryptu w aktualnym katalogu dostaniemy paczkę debianowską nginx-extras-amd64.deb. I już mamy nginxa gotowego do instalacji. 

Skrypt na githubie

 

Share: