it-swarm.com.de

Verwenden von Variablen in Nginx-Standortregeln

In Nginx versuche ich, eine Variable zu definieren, mit der ich einen Unterordner für alle meine Standortblöcke konfigurieren kann. Ich tat dies:

set $folder '/test';

location $folder/ {
   [...]
}

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

Leider scheint dies nicht zu funktionieren. Während Nginx sich nicht über die Syntax beschwert, gibt es bei der Anforderung von /test/ Eine 404 zurück. Wenn ich den Ordner explizit schreibe, funktioniert es. Wie kann ich Variablen in Positionsblöcken verwenden?

47
tomka

Das kannst du nicht. Nginx unterstützt Variablen in Konfigurationsdateien nicht wirklich und seine Entwickler verspotten alle, die nach der Hinzufügung dieser Funktion fragen:

"[Variablen] sind im Vergleich zu einer einfachen statischen Konfiguration ziemlich kostspielig. [A] Makro-Erweiterungs- und" Include "-Anweisungen sollten beispielsweise mit sed + make oder einem anderen gängigen Template-Mechanismus verwendet werden." http: //nginx.org/en/docs/faq/variables_in_config.html

Sie sollten entweder ein kleines Tool schreiben oder herunterladen, mit dem Sie Konfigurationsdateien aus Platzhalter-Konfigurationsdateien generieren können.

Update Der folgende Code funktioniert immer noch, aber ich habe alles in ein kleines PHP Programm/eine kleine Bibliothek namens Configurator gepackt auch auf Packagist , das die einfache Erzeugung von Konfigurationsdateien für Nginx/Php-Fpm usw. aus Vorlagen und verschiedenen Formen von Konfigurationsdaten ermöglicht.

z.B. Meine Nginx-Quellkonfigurationsdatei sieht folgendermaßen aus:

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

Und dann habe ich eine Konfigurationsdatei mit den definierten Variablen:

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

Und dann erstelle ich daraus die eigentliche Konfigurationsdatei. Es sieht so aus, als wären Sie ein Python - Typ. Ein PHP - basiertes Beispiel hilft Ihnen möglicherweise nicht weiter, aber für alle anderen, die PHP verwenden:

<?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);
}

?>

Und dann sieht die Datei deployConfig.ini ungefähr so ​​aus:

[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
65
Danack

Eine modifizierte python Version von @ danacks PHP= Skript generieren. Es generiert alle Dateien und Ordner, die sich innerhalb von build/ Befinden, in das übergeordnete Verzeichnis. Ersetzen aller Übereinstimmungen mit {{placeholder}}. Sie müssen cd in build/ eingeben, bevor Sie das Skript ausführen.

Dateistruktur

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)
2
Ricky Boyce

Sie könnten das Gegenteil von dem tun, was Sie vorgeschlagen haben.

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

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