Подтвердить что ты не робот

Использование переменных в правилах размещения Nginx

В Nginx я пытаюсь определить переменную, которая позволяет мне настроить подпапку для всех моих блоков местоположения. Я сделал это:

set $folder '/test';

location $folder/ {
   [...]
}

location $folder/something {
   [...]
}

К сожалению, это не работает. Хотя Nginx не жалуется на синтаксис, он возвращает 404 при запросе /test/. Если я пишу папку в явном виде, она работает. Итак, как я могу использовать переменные в блоках местоположения?

4b9b3361

Ответ 1

Вы не можете. Nginx на самом деле не поддерживает переменные в файлах конфигурации, и его разработчики издеваются над всеми, кто просит добавить эту функцию:

"[Переменные] являются довольно дорогостоящими по сравнению с простой статической конфигурацией. [A] следует использовать макросы и" включить "директивы [с], например, sed + make или любой другой общий механизм шаблонов". http://nginx.org/en/docs/faq/variables_in_config.html

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

Обновление. Код ниже по-прежнему работает, но я свернул его в небольшую PHP-программу/библиотеку под названием Configurator. также на Packagist, который позволяет легко генерировать файлы конфигурации nginx/php-fpm и т.д. из шаблонов и различных форм данных конфигурации.

например. Мой исходный конфигурационный файл nginx выглядит так:

location  / {
    try_files $uri /routing.php?$args;
    fastcgi_pass   unix:%phpfpm.socket%/php-fpm-www.sock;
    include       %mysite.root.directory%/conf/fastcgi.conf;
}

А потом у меня есть файл конфигурации с определенными переменными:

phpfpm.socket=/var/run/php-fpm.socket
mysite.root.directory=/home/mysite

И затем я создаю фактический файл конфигурации, используя это. Похоже, что вы парень Python, поэтому пример на PHP может не помочь вам, но для тех, кто использует PHP:

<?php

require_once('path.php');

$filesToGenerate = array(
    'conf/nginx.conf' => 'autogen/nginx.conf',
    'conf/mysite.nginx.conf' => 'autogen/mysite.nginx.conf',
    'conf/mysite.php-fpm.conf' => 'autogen/mysite.php-fpm.conf',
    'conf/my.cnf' => 'autogen/my.cnf',
);

$environment = 'amazonec2';

if ($argc >= 2){
    $environmentRequired = $argv[1];

    $allowedVars = array(
        'amazonec2',
        'macports',
    );

    if (in_array($environmentRequired, $allowedVars) == true){
        $environment = $environmentRequired;
    }
}
else{
    echo "Defaulting to [".$environment."] environment";
}

$config = getConfigForEnvironment($environment);

foreach($filesToGenerate as $inputFilename => $outputFilename){
    generateConfigFile(PATH_TO_ROOT.$inputFilename, PATH_TO_ROOT.$outputFilename, $config);
}


function    getConfigForEnvironment($environment){
    $config = parse_ini_file(PATH_TO_ROOT."conf/deployConfig.ini", TRUE);
    $configWithMarkers = array();
    foreach($config[$environment] as $key => $value){
        $configWithMarkers['%'.$key.'%'] = $value;
    }

    return  $configWithMarkers;
}


function    generateConfigFile($inputFilename, $outputFilename, $config){

    $lines = file($inputFilename);

    if($lines === FALSE){
        echo "Failed to read [".$inputFilename."] for reading.";
        exit(-1);
    }

    $fileHandle = fopen($outputFilename, "w");

    if($fileHandle === FALSE){
        echo "Failed to read [".$outputFilename."] for writing.";
        exit(-1);
    }

    $search = array_keys($config);
    $replace = array_values($config);

    foreach($lines as $line){
        $line = str_replace($search, $replace, $line);
        fwrite($fileHandle, $line);
    }

    fclose($fileHandle);
}

?>

И затем deployConfig.ini выглядит примерно так:

[global]

;global variables go here.

[amazonec2]
nginx.log.directory = /var/log/nginx
nginx.root.directory = /usr/share/nginx
nginx.conf.directory = /etc/nginx
nginx.run.directory  = /var/run
nginx.user           = nginx

[macports]
nginx.log.directory = /opt/local/var/log/nginx
nginx.root.directory = /opt/local/share/nginx
nginx.conf.directory = /opt/local/etc/nginx
nginx.run.directory  = /opt/local/var/run
nginx.user           = _www

Ответ 2

Измененная версия python @danack PHP генерирует script. Он генерирует все файлы и папки, которые живут внутри build/, в родительский каталог, заменяя все совпадения {{placeholder}}. Вам нужно cd в build/ перед запуском script.

Структура файла

build/
-- (files/folders you want to generate)
-- build.py

sites-available/...
sites-enabled/...
nginx.conf
...

build.py

import os, re

# Configurations
target = os.path.join('.', '..')
variables = {
  'placeholder': 'your replacement here'
}


# Loop files
def loop(cb, subdir=''):
  dir = os.path.join('.', subdir);

  for name in os.listdir(dir):
    file = os.path.join(dir, name)
    newsubdir = os.path.join(subdir, name)

    if name == 'build.py': continue
    if os.path.isdir(file): loop(cb, newsubdir)
    else: cb(subdir, name)


# Update file
def replacer(subdir, name):
  dir  = os.path.join(target, subdir)
  file = os.path.join(dir, name)
  oldfile = os.path.join('.', subdir, name)

  with open(oldfile, "r") as fin:
    data = fin.read()

  for key, replacement in variables.iteritems():
    data = re.sub(r"{{\s*" + key + "\s*}}", replacement, data)

  if not os.path.exists(dir):
    os.makedirs(dir)

  with open(file, "w") as fout:
    fout.write(data)


# Start variable replacements.
loop(replacer)

Ответ 3

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

location (/test)/ {
   set $folder $1;
}

location (/test_/something {
   set $folder $1;
}