nginx解析配置参数

本节内容

本节分析一下ngx_get_options()函数,这个函数的作用就是解析nginx的启动命令传递的参数,比如/usr/local/nginx/sbin/nginx -s reload/usr/local/nginx/sbin/nginx -t等。


http://nginx.org/en/docs/switches.html

nginx supports the following command-line parameters:

-? | -h — print help for command-line parameters.

-c file — use an alternative configuration file instead of a default file.

-g directives — set global configuration directives, for example,
nginx -g "pid /var/run/nginx.pid; worker_processes `sysctl -n hw.ncpu`;"

-p prefix — set nginx path prefix, i.e. a directory that will keep server files (default value is /usr/local/nginx).

-q — suppress non-error messages during configuration testing.不输出error级别下的信息,配合-t参数使用

-s signal — send a signal to the master process. The argument signal can be one of:
    stop — shut down quickly
    quit — shut down gracefully
    reload — reload configuration, start the new worker process with a new configuration, gracefully shut down old worker processes.
    reopen — reopen log files

-t — test the configuration file: nginx checks the configuration for correct syntax, and then tries to open files referred in the configuration.

-T — same as -t, but additionally dump configuration files to standard output (1.9.2).

-v — print nginx version.

-V — print nginx version, compiler version, and configure parameters.

源码分析

我们先看一下ngx_get_options的源码,如下:

static ngx_int_t
ngx_get_options(int argc, char *const *argv)
{
    u_char     *p;
    ngx_int_t   i;
// 第0个参数是nginx本身,所以从第一个参数进行解析
    for (i = 1; i < argc; i++) {

        p = (u_char *) argv[i];
// 参数必须以短横线开头
        if (*p++ != '-') {
            ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
            return NGX_ERROR;
        }

        while (*p) {

            switch (*p++) {

            case '?':
            case 'h':
                ngx_show_version = 1;
                ngx_show_help = 1;
                break;

            case 'v':
                ngx_show_version = 1;
                break;

            case 'V':
                ngx_show_version = 1;
                ngx_show_configure = 1;
                break;

            case 't':
                ngx_test_config = 1;
                break;

            case 'T':
                ngx_test_config = 1;
                ngx_dump_config = 1;
                break;

            case 'q':
                ngx_quiet_mode = 1;
                break;

            case 'p':
                if (*p) {
                    ngx_prefix = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_prefix = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-p\" requires directory name");
                return NGX_ERROR;

            case 'c':
                if (*p) {
                    ngx_conf_file = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_conf_file = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-c\" requires file name");
                return NGX_ERROR;

            case 'g':
                if (*p) {
                    ngx_conf_params = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_conf_params = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-g\" requires parameter");
                return NGX_ERROR;

            case 's':
                if (*p) {
                    ngx_signal = (char *) p;

                } else if (argv[++i]) {
                    ngx_signal = argv[i];

                } else {
                    ngx_log_stderr(0, "option \"-s\" requires parameter");
                    return NGX_ERROR;
                }

                if (ngx_strcmp(ngx_signal, "stop") == 0
                    || ngx_strcmp(ngx_signal, "quit") == 0
                    || ngx_strcmp(ngx_signal, "reopen") == 0
                    || ngx_strcmp(ngx_signal, "reload") == 0)
                {
                    ngx_process = NGX_PROCESS_SIGNALLER;
                    goto next;
                }

                ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
                return NGX_ERROR;

            default:
                ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
                return NGX_ERROR;
            }
        }

    next:

        continue;
    }

    return NGX_OK;
}

Q1: 为什么有一个while循环?
A1: 一个减号后面可以带有多个参数。比如-thv等。

Q2: 为什么处理-p的时候要先判断一下if(*p)呢?

// 为什么要先判断一次 *p, 然后再判断argv[++i]呢?
         if (*p) {
                    ngx_prefix = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_prefix = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-p\" requires directory name");
                return NGX_ERROR;

A2: 因为nginx-p的参数既可以紧跟着p,也可以和-p中间隔若干个空格。
比如/usr/local/nginx/sbin/nginx -p/usr/local/nginx/html/,也可以/usr/local/nginx/sbin/nginx -p /usr/local/nginx/html/,所以这里有两种处理方式了。
if(*p)是处理第一种中间没有空格的情况。

要知道,argv[]是一个字符串指针数组,每个元素都是以\0结尾的,并且数组的最后一个元素是NULL。所以如果*p != NULL,那么就说明-p的参数是紧挨着-p的。

从这里我们也可以看出来,处理完-p指令之后执行了goto next,而不是break,这里也说明:如果-p指令和其他指令一起使用的时候,-p必须放到最后,比如/usr/local/nginx/sbin/nginx -tp /usr/local/nginx/html/, 而不能是/usr/local/nginx/sbin/nginx -pt /usr/local/nginx/html/。(注意pt的顺序)

参数标志

对于每种参数的解析都是类似的,会设置一个变量。
比如,如果是-v,那么就会设置ngx_show_version = 1等。


TODO: 此处缺少一张概括图

总结

本文就先简单的分析一下启动过程中的解析命令行参数的函数。如果喜欢本文,可以关注公众号Nginx源码分析.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,273评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,349评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,709评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,520评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,515评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,158评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,755评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,660评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,203评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,287评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,427评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,122评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,801评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,272评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,393评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,808评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,440评论 2 359

推荐阅读更多精彩内容