try_files - Usar variables en las reglas de ubicación de Nginx
nginx variables (3)
No puedes. Nginx no admite realmente variables en archivos de configuración, y sus desarrolladores se burlan de todos los que piden que se agregue esta característica:
"[Variables] son bastante costosas en comparación con la configuración estática simple. [A] las directivas de macro expansión y" incluir "deberían usarse [con] por ejemplo sed + make o cualquier otro mecanismo de plantilla común". http://nginx.org/en/docs/faq/variables_in_config.html
Debe escribir o descargar una pequeña herramienta que le permitirá generar archivos de configuración a partir de archivos de configuración de marcador de posición.
Actualización El código siguiente todavía funciona, pero lo he envuelto todo en una pequeña biblioteca / programa PHP llamado Configurator también en Packagist , que permite la generación fácil de archivos de configuración nginx / php-fpm, etc., desde plantillas y varias formas de datos de configuración .
Por ejemplo, mi archivo de configuración de fuente nginx tiene este aspecto:
location / {
try_files $uri /routing.php?$args;
fastcgi_pass unix:%phpfpm.socket%/php-fpm-www.sock;
include %mysite.root.directory%/conf/fastcgi.conf;
}
Y luego tengo un archivo de configuración con las variables definidas:
phpfpm.socket=/var/run/php-fpm.socket
mysite.root.directory=/home/mysite
Y luego genero el archivo de configuración real usando eso. Parece que eres un chico de Python, por lo que un ejemplo basado en PHP puede no ser de ayuda, pero para cualquier otra persona que sí lo use:
<?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);
}
?>
Y luego deployConfig.ini se ve algo así como:
[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
En Nginx, intento definir una variable que me permita configurar una subcarpeta para todos mis bloques de ubicación. Hice esto:
set $folder ''/test'';
location $folder/ {
[...]
}
location $folder/something {
[...]
}
Desafortunadamente, esto no parece funcionar. Si bien Nginx no se queja de la sintaxis, devuelve un 404 al solicitar /test/
. Si escribo la carpeta explícitamente, funciona. Entonces, ¿cómo puedo usar variables en bloques de ubicación?
Podría hacer lo contrario de lo que propuso.
location (/test)/ {
set $folder $1;
}
location (/test_/something {
set $folder $1;
}
Una versión de python modificada del script de PHP de @ danack. Genera todos los archivos y carpetas que viven dentro de la build/
en el directorio padre, reemplazando todas las coincidencias de {{placeholder}}
. Necesita hacer un cd
en build/
antes de ejecutar el script.
Estructura de archivo
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)