14《Nginx 入門教程》Nginx的日志功能

1. Nginx日志功能介紹

通常,在生產(chǎn)環(huán)境中使用 Nginx 進行反向代理和負載均衡或者各種其他處理時,良好的日志記錄是非常關(guān)鍵的一環(huán)斥难。通過精心配置的 Nginx 日志贞让,我們可以獲取用戶的真實 ip、瀏覽器信息甜无,請求處理時間扛点,請求URL等,這樣方便我們排查和回溯錯誤岂丘。具體要記錄哪些信息陵究,可以通過 Nginx 中的 log_format 指令定義,由它定義日志的格式奥帘。而對于使用哪種日志格式和設(shè)置日志的保存路徑則由 access_log 指令指定的铜邮。另外在 Nginx 中還有一個配置服務(wù)器和請求處理過程中的錯誤信息的指令,那就是 error_log指令翩概。最后牲距,如果在配置的日志文件路徑中使用了變量,我們可以通過open_log_file_cache指令來設(shè)置緩存钥庇,提升性能牍鞠。對于大型的網(wǎng)站而言,大量的 http 請求意味著大量的日志記錄评姨,及時按天或按大小進行 Nginx 日志備份也至關(guān)重要的难述。

在 Nginx 的日志模塊主要有2個, ngx_stream_log_module 和 ngx_http_log_module,分別表示四層的日志模塊和七層的日志模塊吐句,其指令和用法都是一致的胁后,接下來我們只針對 http 請求的日志進行說明和使用。

2. 日志相關(guān)指令說明

在 ngx_http_log_module 模塊中嗦枢,只3個指令攀芯,分別是 access_log、log_format 和 open_log_file_cache文虏。這些指令具體的格式如下:

Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default: access_log logs/access.log combined;
Context: http, server, location, if in location, limit_except

Syntax: log_format name [escape=default|json|none] string ...;
Default: log_format combined "...";
Context: http

Syntax: open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
Default: open_log_file_cache off;
Context: http, server, location

ngx_http_log_module 模塊用來按某個格式來記錄請求的日志侣诺。模塊中的 log_format 指令就是用來設(shè)置打印日志的格式殖演,該指令中可以使用 Nginx 中的各種變量,比如保存遠端ip地址的變量$remote_addr等年鸳。一個簡單的示例如下:

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

接下來是 access_log 指令趴久。參考前面的指令格式。關(guān)閉日志記錄搔确,直接是寫access_log off彼棍,如果打開 access 日志,它的寫法是:

access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];

  • path 是指定日志的寫入路徑膳算,默認寫入 logs/access.log 文件中座硕。注意日志路徑可以包變量,但是會一些限制涕蜂。
  • format 就是指定打的日志格式坎吻,也就是前面 log_format 指令定義好的格式。每個格式會設(shè)置一個格式名宇葱,這里取對應(yīng)的格式名稱,默認使用預(yù)定義的combined刊头。
  • buffer 用來指定日志寫入時的緩存大小黍瞧。默認是64k。
  • gzip 日志寫入前先進行壓縮原杂。壓縮率可以指定印颤,從1到9數(shù)值越大壓縮比越高,同時壓縮的速度也越慢穿肄。默認是1年局。
  • flush 設(shè)置緩存的有效時間。如果超過flush指定的時間咸产,緩存中的內(nèi)容將被清空矢否。
  • if 條件判斷。如果指定的條件計算為0或空字符串脑溢,那么該請求不會寫入日志僵朗。

access_log 指令示例:

# 確保 Nginx 源碼編譯時安裝了zlib庫
access_log /path/to/log.gz combined gzip flush=5m;

map $status $loggable {
    ~^[23]  0;
    default 1;
}

# if條件判斷, 如果請求的相應(yīng)碼是2xx或者3xx,那么$loggable變量為0屑彻,這樣請求日志不會被打印
access_log /path/to/access.log main if=$loggable;

每一條日志記錄的寫入都是先打開文件再寫入記錄验庙,然后關(guān)閉日志文件。如果你的日志文件路徑中使用了變量社牲,如access_log /var/logs/$host/access.log粪薛,為提高性能,可以使用 open_log_file_cache 指令設(shè)置日志文件描述符的緩存搏恤∥ナ伲可以通過open_log_file_cache off關(guān)閉該緩存湃交。該指令的幾個參數(shù)選項說明如下:

  • max: 設(shè)置緩存中最多容納的文件描述符數(shù)量,如果被占滿陨界,采用LRU算法將描述符關(guān)閉巡揍。
  • inactive: 設(shè)置緩存存活時間,默認是10s菌瘪。
  • min_uses: 在inactive時間段內(nèi)腮敌,日志文件最少使用幾次,該日志文件描述符記入緩存俏扩,默認是1次糜工。
  • valid: 設(shè)置多久對日志文件名進行檢查,看是否發(fā)生變化录淡,默認是60s捌木。
open_log_file_cache max=100 inactive=15s valid=1m min_uses=2;

最后 error_log 是 錯誤日志配置指令,主要記錄客戶端訪問 Nginx 出錯時的日志嫉戚,它不不支持自定義日志格式刨裆。通過檢查錯誤日志,可以快速定位線上問題彬檀,所以也是很重要的帆啃。關(guān)閉錯誤日志的方式和 access_log不一樣,沒有error_log off這樣關(guān)錯誤日志的用法窍帝,反而會將錯誤日志打到名為 off 的文件中努潘。常用的關(guān)閉方式是:

error_log /dev/null;  

就像在 Linux 系統(tǒng)中,輸出到 /dev/null 的內(nèi)容實際上等價于丟棄一樣坤学。

3. Nginx 日志切割

Nginx 的日志切割實現(xiàn)的核心是使用 nginx 命令的 reopen 參數(shù)實現(xiàn)疯坤,該參數(shù)的含義是重新開始記錄日志文件。人工切的做法就是凌晨將日志備份深浮,然后執(zhí)行帶reopen參數(shù)的命令:

# 備份相關(guān)的日志
[root@server sbin] mv ../logs/access.log ../logs/bak/access-2020-02-04.log
[root@server sbin] mv ../logs/error.log ../logs/bak/error-2020-02-04.log
[root@server sbin] ./nginx -s reopen

執(zhí)行后會重新生成 access.log 和 error.log压怠,這就是手工切割的方式。通常我們會用 shell 腳本和定時任務(wù)來幫我我們完成自動切割略号。首先準(zhǔn)備如下的 shell 腳本刑峡,它完成日志的備份以及給 nginx 進程發(fā)生 reopen 信號。

#!/binbash
NGX_DIR=/root/nginx
NGX_LOG_PATH=$NGX_DIR/logs
NGX_LGO_BAK_PATH=/var/log/ngx_log_bak

YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)

mv ${NGX_LOG_PATH}/access.log ${NGX_LGO_BAK_PATH}/access-${YESTERDAY}.log
mv ${NGX_LOG_PATH}/error.log ${NGX_LGO_BAK_PATH}/error-${YESTERDAY}.log

# 想 Nginx 主進程發(fā)生 USR1 信號玄柠,等價于 -s reopen 選項突梦,重新打開日志文件
kill -USR1 ${NGX_DIR}/log/nginx.pid

接下來,只要將這個腳本加入到 crontab 中即可羽利,如下操作:

$ crontab -e
# 上面打開的頁面中輸入如下行:
0 0 * * *  /root/nginx/nginx_log_rotate.sh

# 查看定時任務(wù)
$ crontab -l
0 0 * * *  /root/nginx/nginx_log_rotate.sh

4. 案例演示

我們在 nginx.conf 中添加如下的日志配置:

...

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    map $status $loggable {
        ~^[34]  0;
        default 1;
    }

    access_log  logs/access.log  main if=$loggable;

    server {
        listen 8000;
        return 200 '8000, server\n';
    }

    server {
        listen 8001;
        return 300 '8001, server\n';
    }

    server {
        listen 8002;
        return 401 '8002, server\n';
    }

    ...
    
}

...


這里我們綜合了前面涉及的知識宫患,這里只簡單測試日志配置中 if 功能。我們設(shè)置請求的相應(yīng)碼為 3xx 和 4xx 時这弧,日志不會記錄娃闲。接下來虚汛,啟動或者熱加載 Nginx, 然后分別對應(yīng)三個端口發(fā)送 http 請求并觀察 access.log 日志:

[shen@shen ~]$ curl http://180.76.152.113:8000 -I
HTTP/1.1 200 OK
Server: nginx/1.17.6
Date: Tue, 04 Feb 2020 13:31:03 GMT
Content-Type: application/octet-stream
Content-Length: 13
Connection: keep-alive

[shen@shen ~]$ curl http://180.76.152.113:8001 -I
HTTP/1.1 300 
Server: nginx/1.17.6
Date: Tue, 04 Feb 2020 13:31:06 GMT
Content-Type: application/octet-stream
Content-Length: 13
Connection: keep-alive

[shen@shen ~]$ curl http://180.76.152.113:8002 -I
HTTP/1.1 401 Unauthorized
Server: nginx/1.17.6
Date: Tue, 04 Feb 2020 13:31:08 GMT
Content-Type: application/octet-stream
Content-Length: 13
Connection: keep-alive

# 到 Nginx 主機上觀察 access.log 日志皇帮,發(fā)現(xiàn)只有響應(yīng)碼為200的請求記錄了日志
[root@server nginx]# tail -f logs/access.log

171.82.186.225 - - [04/Feb/2020:21:33:24 +0800] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.29.0" "-"

5. 小結(jié)

本小節(jié)我們介紹了 log 相關(guān)的指令卷哩,包括訪問日志和錯誤日志的指令。此外還介紹了 Nginx 中對日志切割的常用處理方法属拾,這也是生產(chǎn)環(huán)境上使用日志備份的手段将谊。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市渐白,隨后出現(xiàn)的幾起案子尊浓,更是在濱河造成了極大的恐慌,老刑警劉巖纯衍,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栋齿,死亡現(xiàn)場離奇詭異,居然都是意外死亡襟诸,警方通過查閱死者的電腦和手機瓦堵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歌亲,“玉大人谷丸,你說我怎么就攤上這事∮幔” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵泉唁,是天一觀的道長鹅龄。 經(jīng)常有香客問我,道長亭畜,這世上最難降的妖魔是什么扮休? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮拴鸵,結(jié)果婚禮上玷坠,老公的妹妹穿的比我還像新娘。我一直安慰自己劲藐,他們只是感情好八堡,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著聘芜,像睡著了一般兄渺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上汰现,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天挂谍,我揣著相機與錄音叔壤,去河邊找鬼。 笑死口叙,一個胖子當(dāng)著我的面吹牛炼绘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播妄田,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼俺亮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了形庭?” 一聲冷哼從身側(cè)響起铅辞,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎萨醒,沒想到半個月后斟珊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡富纸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年囤踩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晓褪。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡堵漱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涣仿,到底是詐尸還是另有隱情勤庐,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布好港,位于F島的核電站愉镰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏钧汹。R本人自食惡果不足惜丈探,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拔莱。 院中可真熱鬧碗降,春花似錦、人聲如沸塘秦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尊剔。三九已至精偿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背笔咽。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工搔预, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叶组。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓拯田,卻偏偏與公主長得像,于是被迫代替她去往敵國和親甩十。 傳聞我的和親對象是個殘疾皇子船庇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容