ログローテートの記事を書くためのサンプルとしてとりあえず追っていく記事。ログローテートの設定は別でやる必要があるのでこの記事のサンプルで動作するときの流れをイメージして書いていく。
SIGUSR1はsrc/core/ngx_config.h
でdefineされている
#define NGX_REOPEN_SIGNAL USR1
masterがsrc/os/unix/ngx_process.c
辺りでシグナルハンドラを設定する。シグナルが送られたらngx_reopen
というフラグを立てる
case ngx_signal_value(NGX_REOPEN_SIGNAL): ngx_reopen = 1; action = ", reopening logs"; break;
ngx_master_process_cycle
の中でreopenフラグが立っていると子プロセスにSIGUSR1を送出する。
if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); }
子プロセスはngx_reopen_files
を呼び出す。
if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, -1); }
ここが最終的に呼ばれる
void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; part = &cycle->open_files.part; // オープンしているファイル file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { // 読み切ったらbreak break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } if (file[i].flush) { file[i].flush(&file[i], cycle->log); } fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); // O_CRETEを指定しているので存在しなければ作成 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { // close処理は直後に実施 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } file[i].fd = fd; } (void) ngx_log_redirect_stderr(cycle); }
ざっくり読んだ。ログローテートに対応するログ監視ツールを書く場合に気をつけることという記事を次に書く予定。