Nginx 소스 코드 분석 - 주류 프로 세 스 - 부 드 러 운 재 부팅 과 신호 제어 (10)

목차
부 드 럽 게 다시 시작
신호 처리
부 드 럽 게 다시 시작
지난 글 에서 우 리 는 Nginx 의 시작 절 차 를 분석 했다.그 중 ngxadd_inherited_sockets 는 주로 Socket 파일 핸들 을 계승 하 는 데 사 용 됩 니 다.
Nginx 는 부 드 럽 게 다시 시작 하 는 기능 이 있 습 니 다. 부 드 럽 게 다시 시작 하면 사용자 가 감지 하지 않 고 중단 하지 않 을 수 있 습 니 다.
#      
sudo kill -HUP `cat /usr/local/nginx-1.4.7/nginx.pid`  

Nginx 는 열 전환 을 지원 합 니 다. 전환 후의 소켓 을 잃 어 버 리 지 않도록 Nginx 가 원래 의 socket (사용자 가 Nginx 에 연결 하고 있 을 때의 파일 핸들) 을 계승 해 야 합 니 다.
ngx_add_inherited_sockets 가 바로 이 일 을 했 습 니 다.
소켓 은 'NGINX' 의 전역 환경 변수 에 놓 입 니 다.
계승 한 socket 파일 핸들 을 ngxcycle. listening 배열 중.
    /*    socket    ,    80    ;
     * Nginx     ,               ,
     *               Socket   ,      NGINX        */
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

NGINX 매크로 변수의 값, 클 라 이언 트 의 socket fd 핸들 값:
NGINX="16000:16500:16600;"

구체 함수 구현:
/**
 * Nginx     ,               ,              Socket   ,      NGINX        
 *       sockets
 *         NGINX  socket   ,    socket    init_cycle listening   。
 *  NGINX     ,  socket          。            ngx_inherited 1。
 */
static ngx_int_t
ngx_add_inherited_sockets(ngx_cycle_t *cycle)
{
    u_char           *p, *v, *inherited;
    ngx_int_t         s;
    ngx_listening_t  *ls;

    /*        NGINX        :# export NGINX="16000:16500:16600;" */
    inherited = (u_char *) getenv(NGINX_VAR);

    if (inherited == NULL) {
        return NGX_OK;
    }

    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
                  "using inherited sockets from \"%s\"", inherited);

    /*    ngx_cycle.listening  ,       10    */
    if (ngx_array_init(&cycle->listening, cycle->pool, 10,
                       sizeof(ngx_listening_t))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    for (p = inherited, v = p; *p; p++) {
        if (*p == ':' || *p == ';') {
            s = ngx_atoi(v, p - v);
            if (s == NGX_ERROR) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                              "invalid socket number \"%s\" in " NGINX_VAR
                              " environment variable, ignoring the rest"
                              " of the variable", v);
                break;
            }

            v = p + 1;

            ls = ngx_array_push(&cycle->listening);
            if (ls == NULL) {
                return NGX_ERROR;
            }

            ngx_memzero(ls, sizeof(ngx_listening_t));

            /*  fd   ngx_listening_t      */
            ls->fd = (ngx_socket_t) s;
        }
    }

    if (v != p) {
        ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                      "invalid socket number \"%s\" in " NGINX_VAR
                      " environment variable, ignoring", v);
    }

    /*          socket */
    ngx_inherited = 1;

    return ngx_set_inherited_sockets(cycle);
}

신호 처리
  • 우리 가 사용 할 때. / nginx - s stop | reload | quit  이와 같은 명령 은 Nginx 에 신 호 를 보 냈 다.
  • 신 호 는 Nginx 프로 세 스 의 재 부팅, 정지, 종료 등 을 제어 할 수 있 습 니 다.시 작 된 Nginx 프로 세 스 PID 를 가 져 와 프로 세 스에 신 호 를 보 냅 니 다.
  • Nginx 의 프로 세 스 ID pid 는 보통 / usr / local / nginx - 1.4.7 / nginx. pid 에 설 치 됩 니 다.
  •     /*     ;  ./nginx -s stop,   Nginx      */
        if (ngx_signal) {
            return ngx_signal_process(cycle, ngx_signal);
        }

    ngx_signal 변 수 는 ngxget_options 방법 중.ngx_signal 은 주로 신호 조작 에 속 하 는 지 여 부 를 표시 하 는 데 사용 된다.예 를 들 어:. / nginx - s stop | reload | quit
                    /* ngx_signal        ./nginx -s stop|reload|quit */
                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;
    

    그리고 ngxsignal_process 의 구체 적 인 조작:
    /**
     *     ;
     *   ./nginx -s stop,   Nginx     
     */
    ngx_int_t
    ngx_signal_process(ngx_cycle_t *cycle, char *sig)
    {
        ssize_t           n;
        ngx_pid_t         pid;
        ngx_file_t        file;
        ngx_core_conf_t  *ccf;
        u_char            buf[NGX_INT64_LEN + 2];
    
        ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started");
    
        ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
    
        ngx_memzero(&file, sizeof(ngx_file_t));
    
        file.name = ccf->pid;
        file.log = cycle->log;
    
        /*   /usr/local/nginx/logs/nginx.pid     ID  */
        file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY,
                                NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS);
    
        if (file.fd == NGX_INVALID_FILE) {
            ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
                          ngx_open_file_n " \"%s\" failed", file.name.data);
            return 1;
        }
    
        n = ngx_read_file(&file, buf, NGX_INT64_LEN + 2, 0);
    
        if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          ngx_close_file_n " \"%s\" failed", file.name.data);
        }
    
        if (n == NGX_ERROR) {
            return 1;
        }
    
        while (n-- && (buf[n] == CR || buf[n] == LF)) { /* void */ }
    
        /*     PID */
        pid = ngx_atoi(buf, ++n);
    
        if (pid == (ngx_pid_t) NGX_ERROR) {
            ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
                          "invalid PID number \"%*s\" in \"%s\"",
                          n, buf, file.name.data);
            return 1;
        }
    
        /*   ngx_os_signal_process  ,        */
        return ngx_os_signal_process(cycle, sig, pid);
    
    }

     
    /**
     *     
     */
    ngx_int_t
    ngx_os_signal_process(ngx_cycle_t *cycle, char *name, ngx_pid_t pid)
    {
        ngx_signal_t  *sig;
    
        for (sig = signals; sig->signo != 0; sig++) {
            if (ngx_strcmp(name, sig->name) == 0) {
    
            	/*                */
                if (kill(pid, sig->signo) != -1) {
                    return 0;
                }
    
                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                              "kill(%P, %d) failed", pid, sig->signo);
            }
        }
    
        return 1;
    }
    

    좋은 웹페이지 즐겨찾기