Skip to main content
 首页 » 编程设计

variables之在 Nginx 位置规则中使用变量

2024年05月10日33grandyang

在 Nginx 中,我尝试定义一个变量,该变量允许我为所有位置 block 配置子文件夹。我这样做了:

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

不幸的是,这似乎不起作用。虽然 Nginx 不会提示语法,但它在请求 /test/ 时会返回 404。如果我明确地写入该文件夹,它就可以工作。那么如何在位置 block 中使用变量呢?

请您参考如下方法:

你不能。 Nginx 并不真正支持配置文件中的变量,它的开发者 mock 所有要求添加此功能的人:

"[Variables] are rather costly compared to plain static configuration. [A] macro expansion and "include" directives should be used [with] e.g. sed + make or any other common template mechanism." http://nginx.org/en/docs/faq/variables_in_config.html

您应该编写或下载一个小工具,它允许您从占位符配置文件生成配置文件。

更新 下面的代码仍然有效,但我已将其全部打包到一个名为 Configurator 的小型 PHP 程序/库中。也在 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