转载自:http://www.linuxidc.com/Linux/2014-12/110989.htm
作为Web服务器而言,日志是必不可少的也是需要经常查看的。此篇就来介绍下如何自定义Nginx中的日志格式以及使用crontab计划任务来做到每天切割一次日志文件从而做到方便管理。
在Nginx中日志文件是由log_format这个指令来定义的,它的语法如下:
log_format name format
# name:指的是日志格式的名称(后面调用)
# format:设置日志具体格式的
在Nginx中有自己默认的日志格式,如下内容:
# log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
默认给注释掉了,看一下解释吧。
$remote_addr | 客户端的ip地址(如果中间有代理服务器那么这里显示的ip就为代理服务器的ip地址) |
$remote_user | 用于记录远程客户端的用户名称(一般为“-”) |
$time_local | 用于记录访问时间和时区 |
$request | 用于记录请求的url以及请求方法 |
$status | 响应状态码 |
$body_bytes_sent | 给客户端发送的文件主体内容大小 |
$http_user_agent | 用户所使用的代理(一般为浏览器) |
$http_x_forwarded_for | 可以记录客户端IP,通过代理服务器来记录客户端的ip地址 |
$http_referer | 可以记录用户是从哪个链接访问过来的 |
有时候可能就算启用了$http_x_forwarded_for也无法获取客户端的ip地址详情请参考此篇博文:Nginx 日志获取不到远程访问ip问题解决 http://www.linuxidc.com/Linux/2014-12/110990.htm
定义好日志格式后,我们还需要引用它:
access_log /usr/nginx_logs/access/qzj.access.log main;
/usr/nginx_logs/access/qzj.access.log 为日志存放路径
main 为上边定义的日志格式名称
自定义日志就结束了,接下来就是切割日志文件并且每天保存一份当天的日志文件方法如下:
首先将原来的日志文件重命名
mv test1.access.log test1.2014-12-29.log
nginx -s reload
这样就可以做到日志文件的切割。如果要每天自动保存的话就要基于crontab来管理了。写个脚本吧
<span style="font-size:14px;">#!/bin/bash
vhost=qzj
# 指定日志文件要保存位置
log_path=/usr/nginx_logs
# 指定access日志所在路径
access_log_path=/usr/nginx_logs/access
# pid文件路径
pid_path=/usr/local/nginx/logs/nginx.pid
# 创建日期目录,date -d "yesterday" +"%y"获取年份后面那个是获取月份
mkdir -p ${log_path}/$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +%m)/
# 这里将访问日志文件移动到备份的目录中如:/web/vhost/logs/14/12/28.test1.access.log
mv ${access_log_path}/${vhost}.access.log ${log_path}/$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +%m)/$(date -d "yesterday" +%d).${vhost}.access.log
# 重新生成日志文件
kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid)
</span>
我们可以将上边的脚本命名为(可以随便命名):nginx_logs.sh
接下来我们需要把这个脚本加入到crontab中,实现定时对日志文件进行分割。
# crontab -e
如果提示:
no crontab for root using an empty one
那么我们需要先进行如下操作:
<span style="font-size:14px;"> 1、登录到root用户。
2、在root下输入:crontab -e
3、可能会提示你:
no crontab for root - using an empty one
然后会叫你“Select a editor ......”下面有几个选项,就是叫你选择编辑器。(选vim.tiny)
或直接进入编辑页面。
4、进入crontab编辑页面之后就直接"shift+:",然后输入wq保存即可。然后一个新的crontab就生成了!</span>
然后再进行:
# crontab -e
加入:
<span style="font-size:14px;"># nginx日志定时分割任务,运行的脚本路径,此处我们放在了nginx的bin目录下了,创建一个bin目录就可以了
# 此命令的含义是每天12点进行日志分割
00 00 * * * /bin/bash /usr/local/nginx/bin/nginx_log.sh
# 我们可以先测试一下,设定一个较短的时间,比如下边就会在任意小时的11分的时候执行
</span><pre name="code" class="html"><span style="font-size:14px;">11 * * * * /bin/bash /usr/local/nginx/bin/nginx_log.sh</span>
:wq保存退出,不需要重启
对 kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid) 的理解
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在没有执行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)
crontab 格式
------------------------------------------------------------------------------------------------------------------------------------------------------------------
第1列分钟1~59第2列小时1~23(0表示子夜)第3列日1~31第4列月1~12第5列星期0~6(0表示星期天)第6列要运行的命令
下面是crontab的格式:分 时 日 月 星期 要运行的命令
这里有crontab文件条目的一些例子:
<span style="font-size:14px;">30 21 * * * /usr/local/apache/bin/apachectl restart
上面的例子表示每晚的21:30重启apache。
45 4 1,10,22 * * /usr/local/apache/bin/apachectl restart
上面的例子表示每月1、10、22日的4 : 45重启apache。
10 1 * * 6,0 /usr/local/apache/bin/apachectl restart
上面的例子表示每周六、周日的1 : 10重启apache。
0,30 18-23 * * * /usr/local/apache/bin/apachectl restart
上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启apache。
0 23 * * 6 /usr/local/apache/bin/apachectl restart
上面的例子表示每星期六的11 : 00 pm重启apache。
* */1 * * * /usr/local/apache/bin/apachectl restart
每一小时重启apache
* 23-7/1 * * * /usr/local/apache/bin/apachectl restart
晚上11点到早上7点之间,每隔一小时重启apache
0 11 4 * mon-wed /usr/local/apache/bin/apachectl restart
每月的4号与每周一到周三的11点重启apache
0 4 1 jan * /usr/local/apache/bin/apachectl restart
一月一号的4点重启apache
</span>