在Nginx位置规则中使用variables

在Nginx中,我试图定义一个variables,它允许我为所有的位置块configuration一个子文件夹。 我做到了这一点:

set $folder '/test'; location $folder/ { [...] } location $folder/something { [...] } 

不幸的是,这似乎并不奏效。 虽然Nginx不会抱怨语法,但在请求/test/时会返回404。 如果我明确写入文件夹,它的作品。 那么如何在位置块中使用variables?

你不能。 Nginx并不真正支持configuration文件中的variables,其开发人员嘲笑要求添加此function的所有人:

“[variables]与普通的静态configuration相比是相当昂贵的[A]macros扩展和”include“指令应该用于[例如sed + make或其他常见的模板机制]。 http://nginx.org/en/docs/faq/variables_in_config.html

您应该编写或下载一个小工具,使您可以从占位符configuration文件生成configuration文件。

更新下面的代码仍然可以工作,但是我已经把它们全部包装到Packagist上的一个名为Configurator的小型PHP程序/库中,它允许从模板和各种forms的configuration数据中轻松生成nginx / php-fpm等configuration文件。

例如我的nginx源代码configuration文件如下所示:

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

然后我有一个定义variables的configuration文件:

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

然后我使用它生成实际的configuration文件。 它看起来像你是一个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 

修改后的python版本的@ danack的PHP生成脚本。 它会生成生成到父目录中的所有文件和文件夹,取代所有{{placeholder}}匹配。 在运行脚本之前,您需要cdbuild/

文件结构

 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) 

你可以做你的build议相反。

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