天天看點

nginx日志檔案切割

對網上幾篇寫的不錯的nginx日志切割文檔進行梳理:

(一)

nginx使用 logrotate 切割日志

大體上有三種方法切割nginx日志。

第一種是寫個定時任務,每天零點把舊的日志重命名,并對nginx程序發送USR1信号使其重新打開日志并寫入。

第二種是能過管道的方式把新産生的日志寫到另外一個日志檔案裡。

第三種是能過logrotate來切割日志,logrotate是系統自帶的服務,可以切割任何日志,不僅僅是nginx,這裡推薦使用它。

步驟1:

檔案内容如下

步驟2:測試是否可用

步驟3:配置定時任務

完成!

(二)使用定時任務重命名切割日志

nginx 日志檔案切割

連接配接位址:http://www.cnblogs.com/benio/archive/2010/10/13/1849935.html

Nginx 是一個非常輕量的 Web 伺服器,體積小、性能高、速度快等諸多優點。但不足的是也存在缺點,比如其産生的通路日志檔案一直就是一個,不會自動地進行切割,如果通路量很大的話,将 導緻日志檔案容量非常大,不便于管理。當然了,我們也不希望看到這麼龐大的一個通路日志檔案,那需要手動對這個檔案進行切割。

在 Linux 平台上 Shell 腳本豐富,使用 Shell 腳本加 crontab 指令能非常友善地進行切割,但在 Windows 平台上就麻煩一些了,剛才弄了好長時間,就在這裡記錄整理一下。

日志檔案切割要求

由于 Nginx 的日志都是寫在一個檔案當中的,是以,我們需要每天零點将前一天的日志存為另外一個檔案,這裡我們就将 Nginx 位于 logs 目錄中的 access.log 存為 access_[yyyy-MM-dd].log 的檔案。其實 logs 目錄中還有個 error.log 的錯誤日志檔案,這個檔案也需要每天切割一個,在這裡就說 access.log 了,error.log 的切割方法類似。

Linux 平台切割

在 Linux 平台上進行切割,需要使用 date 指令以獲得昨天的日期、使用 kill 指令向 Nginx 程序發送重新打開日志檔案的信号,以及 crontab 設定執行任務周期。

先建立一個 Shell 腳本,如下:

Shell代碼 

#!/bin/bash

## 零點執行該腳本

## Nginx 日志檔案所在的目錄

LOGS_PATH=/usr/local/nginx/logs

## 擷取昨天的 yyyy-MM-dd

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

## 移動檔案

mv ${LOGS_PATH}/access.log ${LOGS_PATH}/access_${YESTERDAY}.log

## 向 Nginx 主程序發送 USR1 信号。USR1 信号是重新打開日志檔案

kill -USR1 $(cat /usr/local/nginx/nginx.pid)

上面這個腳本中的最後一行必須向 Nginx 的程序發送 USR1 信号以重新打開日志檔案,如果不寫的話,Nginx 會繼續将日志資訊寫入 access_[yyyy-MM-dd].log 的那個檔案中,這顯然是不正确的。

腳本完成後将其存入 Nginx 安裝目錄的 sbin 中,取名為 cut-log.sh,之後使用 crontab -e 新增一個定時任務,在其中增加執行這個腳本:

0 0 * * * /bin/bash /usr/local/nginx/sbin/cut-log.sh

到這裡 Linux 下切割 Nginx 日志就完成了,可以将 crontab 設定為距目前時較近的時間測試一下,否則在零點出問題就不好了 。

Windows 平台切割

要在 Windows 平台上做這件事情就有點麻煩了。在 Windows 中沒有原生的指令能夠獲得昨天的日期,Windows 中的計劃任務設定我感覺也沒有 Linux 的 crontab 用得友善,再有批處理指令也沒有 Shell 腳本功能強大。總之,逐一來解決這些問題吧。

新浪部落格上有一篇文章 nginx for windows日志切割,但這篇文章有兩個不足之處:切割後的日志檔案不是以昨天的日期命名;需要停止 Nginx 服務。為了切割日志停止服務,我認為有所不值,如果通路量較小的話問題不大,但是通路量較大的話這種做法是非常不可取的。為了彌補這些缺陷,我們對這個批處理檔案進行了改進。

要 Windows 平台上使用 Linux 的 date 指令以獲得昨天的日期,我們可以到 SourceForge上去下載下傳 UnxUtils這 個工具。UnxUtils 是個非常強大的工具集,将大多數的 Linux 指令都移植到 Windows 平台上來了,比如:ls, grep, wc 等等 120 個指令,當然了其中也包括了我們需要的 date 工具。将這個工具解壓到一個目錄中,假定是 d:\common-path\UnxUtils 目錄中,将那些工具所在的 d:\common-path\UnxUtils\usr\local\wbin 添加到系統的環境變量 PATH 中,可以加到最後去。由于 Windows 平台中有 date 内置指令,是以需要将 UnxUtils 的 date.exe 改名為其他的,比如改為 udate.exe。用 cmd 打開控制台,輸入:

如果能正确輸出昨天日期的話,那麼這一點我們就搞定了 。

接下來需要寫一個批處理檔案,假定我們的 Nginx 是放在 d:\httpServer\nginx-0.7.64 目錄中的,我們就在這個目錄中建一個 cut-log.bat 的檔案:

Batch代碼 

@echo off

rem  擷取昨天的日期,存入 YESTERDAY 變量,udate 參數中的 % 需要改成 %% 進行轉義

for /f %%a in (‘udate -d ”yesterday” +%%Y-%%m-%%d’) do set YESTERDAY=%%a

rem 設定 Nginx 位于的盤符

set NGINX_DRIVER=d:

rem 設定 Nginx 的主目錄

set NGINX_PATH=%NGINX_DRIVER%\green\httpServer\nginx-0.7.64

rem 設定 Nginx 的日志目錄

set LOG_PATH=%NGINX_PATH%\logs

rem 移動檔案

move %LOG_PATH%\access.log %LOG_PATH%\access_%YESTERDAY%.log

rem 切換到 Nginx 所在的盤符

%NGINX_DRIVER%

rem 進入 Nginx 的主目錄

cd %NGINX_PATH%

rem 向 nginx 發送 reopen 信号以重新打開日志檔案,功能與 Linux 平台中的 kill -USR1 一緻

nginx -s reopen

echo on

這個批處理寫好後,将其加入 Windows 的計劃任務中,設定為每天零時執行。需要注意的是,在執行 nginx -s reopen 指令時,目前目錄必須位于 Nginx 的主目錄中,否則會找不到日志檔案在哪個目錄中(估計 Nginx 預設采用相對路徑尋找),這也就是批進行中需要進入盤符和 Nginx 主目錄的原因了,因為任務計劃執行時并不是在 Nginx 的主目錄中。

結束語

這裡主要介紹了一下 Linux 平台和 Windows 平台上切割 Nginx 日志檔案的方法。Linux 中可以直接使用一些内置的指令完成,而在 Windows 中需要裝載 UnxUtils 工具,不過這個工具集非常有用,比如使用其中的 tail 指令,我們在 Windows 中也能很友善地在控制台中使用 tail -f 實時地檢視日志檔案的輸出。

(三)

nginx自動切割通路日志

Web 通路日志 (access_log) 記錄了所有外部用戶端對Web伺服器的通路行為,包含了用戶端IP,通路日期,通路的URL資源,伺服器傳回的HTTP狀态碼等重要資訊。

一條典型的Web通路日志如下:

112.97.37.90 - - [14/Sep/2013:14:37:39 +0800] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Linux; U; Android 2.3.6; zh-cn; Lenovo A326 Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MicroMessenger/4.5.1.259" -

規劃:

1、  要解決問題:

當網站通路量大後,日志資料就會很多,如果全部寫到一個日志檔案中去,檔案會變得越來越大。檔案大速度就會慢下來,比如一個檔案幾百兆。寫入日志的時候,會影響操作速度。另外,如果我想看看通路日志,一個幾百兆的檔案,下載下傳下來打開也很慢。使用第三方免費的日志分析工具-日志寶,可以上傳nginx、apache、iis的日志檔案,它們幫助分析網站安全方面。畢竟專攻,更加專業。日志寶對上傳的檔案也是做了大小限制的,不超過50m。

2、nignx沒有自動分開檔案存儲日志的機制。由于nginx它不會幫你自動分檔案儲存。是以,需要自己編寫腳本來實作。

shell腳本檔案nginx_log_division.sh内容如下:

# /bin/bash

logs_path="/data/wwwlogs/"

#以前的日志檔案。

log_name="xxx.log"   

pid_path="/usr/local/nginx/logs/nginx.pid"

mv ${logs_path}${log_name} ${logs_path}${log_name}_$(date --date="LAST   WEEK" +"%Y-%m-d").log

kill -USR1 `cat ${pid_path}`

上面shell腳本的原理是:先把以前的日志檔案移動重命名成一個,目的是就是備份。

按照上個周一的本日來命名,運作腳本的時候時間點是”2013-09-16”,那麼生成檔案名稱是”xxx.log_ 20130909.log”。

在沒有執行kill -USR1 `cat ${pid_path}`之前,即便已經對檔案執行了mv指令而改變了檔案名稱,nginx還是會向新命名的檔案” xxx.log_ 20130909”照常寫入日志資料的。原因在于:linux系統中,核心是根據檔案描述符來找檔案的。

----------------對linux檔案描述符的了解

檔案描述符是linux核心為每個打開的檔案命名的一個整數辨別。

linux核心為每一個程序生成(或者說維護)一個”檔案描述符表”,這個檔案描述符表記錄的是“此程序所打開的檔案(進行辨別)”。

在這裡的環境中,nginx就是一個運作中的程序,這個程序早就打開了一個日志檔案,在檔案描述符表是記錄了檔案的。

即便日志檔案的路徑改變了,但是還是能夠找到(根據檔案描述符表可以定位)。

 ----------------------------------------------

當執行指令“kill -USR1 `cat ${pid_path}`”的時候,nginx.pid檔案中儲存的其實就是一個數字(自己可以打開看一下,我這裡是894),nginx 将其主程序的 pid (程序号)寫入到了nginx.pid 檔案中,是以可以通過cat指令直接拿到其主程序号,直接操作指定的程序号。

kill  -USR1 `cat ${pid_path}` 就等同于

kill –USR1 894  #指定發信号(USR1)信号給這個程序編号。

在linux系統中,linux是通過信号與”正在運作的程序”進行通信的。linux系統中,也很多預定義好的信号,像SIGHUP。USR1是使用者自定義信号。可以了解為:程序自己定義接到這個信号該幹嘛(也就是程序編寫者自己确定收到這個信号幹嘛還是什麼都不做都行,完全交給開發人員自己決定)。而在nginx中,它自己編寫了代碼處理當我接到USR1信号的時候,讓nginx重新打開日志檔案。具體原理如下:

1、nginx 的主程序收到USR1信号,會重新打開日志檔案(以nginx配置檔案中的日志名稱命名,就是配置檔案中access_log項所設定的值,如果檔案不存在,會自動建立一個新的檔案xxx.log)。

2、然後把日志檔案的擁有者改為“工作程序(worker程序)”,目的是讓worker程序就具備了對日志檔案的讀寫權限(master和worker通常以不同使用者運作,是以需要改變擁有者)。

3、nginx主程序會關閉重名的日志檔案(也就是剛才使用mv指令重命名成xxx.log_ 20130909.log的檔案),并通知工作程序使用新打開的日志檔案(剛才主程序打開的檔案xxx.log)。具體實作上更細化點就是,主程序把USR1信号發給worker,worker接到這個信号後,會重新打開日志檔案(也就是配置檔案中約定的xxx.log)

  ===================================定時執行腳本

 設定上面的shell腳本檔案加入到定時任務中去。crontab是linux下面一個定時任務程序。開機此程序會啟動,它每隔一定時間會去自己的清單中看是否有需要執行的任務。

crontab  -e

* 04 * * 1 /data/wwwlogs/nginx_log_division.sh

會打開一個檔案,加入上面的代碼

格式為 "分 時 日 月 星期幾  要執行的shell檔案路徑"。用*可以了解成“每”,每分鐘,每個小時,每個月等等。

我設定是在周一淩晨4點運作nginx_log_division.sh腳本,腳本的内容就是重新生成一個新的日志檔案。

附:設定nginx日志的配置方法

log_format  site  '$remote_addr - $remote_user [$time_local] "$request" '

             '$status $body_bytes_sent "$http_referer" '

             '"$http_user_agent" $http_x_forwarded_for';

access_log  /data/wwwlogs/xxxx.com.log  site

#第二個參數表示使用那個日志格式,為每一個日志格式辨別了一個名稱,site對應的就是log_format中的名稱 

以上涉及到crontab定時任務管理器的使用知識。

linux中logrotate對日志進行切割壓縮(nginx,mysql)

http://www.111cn.net/sys/linux/61133.htm