在Nginx中,我试图定义一个变量,它允许我为所有位置块配置一个子文件夹。我这样做:在Nginx位置规则中使用变量
set $folder '/test';
location $folder/ {
[...]
}
location $folder/something {
[...]
}
不幸的是,这似乎并不奏效。虽然Nginx不会抱怨语法,但在请求/test/
时会返回404。如果我明确写入文件夹,它就会起作用。那么如何在位置块中使用变量?
在Nginx中,我试图定义一个变量,它允许我为所有位置块配置一个子文件夹。我这样做:在Nginx位置规则中使用变量
set $folder '/test';
location $folder/ {
[...]
}
location $folder/something {
[...]
}
不幸的是,这似乎并不奏效。虽然Nginx不会抱怨语法,但在请求/test/
时会返回404。如果我明确写入文件夹,它就会起作用。那么如何在位置块中使用变量?
你不能。 Nginx的真的不支持配置文件中的变量,它的开发嘲笑添加大家谁问这个功能:
“[变量]是相当昂贵相比,纯静态配置[A]宏扩展和应使用“include”指令[例如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
你可以做你提议的相反。
location (/test)/ {
set $folder $1;
}
location (/test_/something {
set $folder $1;
}
这会是什么好处? – nus 2014-04-28 23:49:07
我假设问题的作者试图告诉Nginx他的应用程序期望的URL。我只是建议,而不是那样做,Nginx可以告诉他的应用程序使用什么网址来访问它。匹配([^ /] +)比匹配(/ test)更有用,就像我给出的例子,但结果是一样的。 – rstackhouse 2014-05-02 19:15:32
修正的python版本的@ danack的PHP生成脚本。它生成所有文件&生活在build/
内的父文件夹,替换所有{{placeholder}}
匹配的文件夹。在运行脚本之前,您需要将cd
转换为build/
。
文件结构
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)
如果您使用python,建议使用jinja模板恕我直言 – Boaz 2017-08-21 06:20:39
好了,感谢你的答案并分享您解决这一问题。 – tomka 2013-03-15 18:24:52
感谢您的回复。为什么开发人员不允许这些变量的特定原因? – 2015-04-20 15:59:25
http:// nginx。org/en/docs/faq/variables_in_config.html“变量不应该作为模板宏使用,变量在处理每个请求的过程中会在运行时进行评估,因此与纯静态配置相比,它们相当昂贵。存储静态字符串也是一个坏主意,相反,应该使用宏扩展和“include”指令更容易地生成配置,并且可以使用外部工具完成,例如sed + make或任何其他常用模板机制。 – Danack 2015-04-20 16:01:04