nginx解析啓動參數

本節內容

本節分析一下ngx_get_options()函數,這個函數的做用就是解析nginx的啓動命令傳遞的參數,好比/usr/local/nginx/sbin/nginx -s reload/usr/local/nginx/sbin/nginx -t等。html

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 versionand configure parameters.
複製代碼

源碼分析

咱們先看一下ngx_get_options的源碼,以下:nginx

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等。web

Q2: 爲何處理-p的時候要先判斷一下if(*p)呢?sql

// 爲何要先判斷一次 *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的。app

從這裏咱們也能夠看出來,處理完-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: 此處缺乏一張歸納圖ui

總結

本文就先簡單的分析一下啓動過程當中的解析命令行參數的函數。若是喜歡本文,能夠關注公衆號Nginx源碼分析.spa

相關文章
相關標籤/搜索