nginx正确的logrotate配置
nginx默认的logrotate配置如下
[ec2-user@rpc_ngx ~]$ cat /etc/logrotate.d/nginx /var/log/nginx/*log { create 0664 nginx root daily rotate 10 missingok notifempty compress sharedscripts postrotate /etc/init.d/nginx reopen_logs endscript }
每天早上0点的时候会对所有的log文件切分,压缩,轮转,然后调用 `nginx reopen_logs`.
如果你像我们需要对nginx logs进行分析的话
- 发现存在.gz文件就将这个文件copy到aws s3上
- 在aws上运行emr对s3上文件进行分析
那么你会发现这个gzip文件是不完整的。EMR日志会出现下面这些错误
19/04/23 08:35:02 INFO HadoopRDD: Input split: s3a://fm.castbox.data.nginx-logs/sync_server_access/201904/20190423-app1.gz:0+542490624 Traceback (most recent call last): File "/mnt/yarn/usercache/hadoop/appcache/application_1556007841411_0001/container_1556007841411_0001_02_000002/pyspark.zip/pyspark/daemon.py", line 170, in manager File "/mnt/yarn/usercache/hadoop/appcache/application_1556007841411_0001/container_1556007841411_0001_02_000002/pyspark.zip/pyspark/daemon.py", line 73, in worker File "/mnt/yarn/usercache/hadoop/appcache/application_1556007841411_0001/container_1556007841411_0001_02_000002/pyspark.zip/pyspark/worker.py", line 397, in main if read_int(infile) == SpecialLengths.END_OF_STREAM: File "/mnt/yarn/usercache/hadoop/appcache/application_1556007841411_0001/container_1556007841411_0001_02_000002/pyspark.zip/pyspark/serializers.py", line 714, in read_int raise EOFError EOFError Traceback (most recent call last): File "/mnt/yarn/usercache/hadoop/appcache/application_1556007841411_0001/container_1556007841411_0001_02_000002/pyspark.zip/pyspark/daemon.py", line 170, in manager File "/mnt/yarn/usercache/hadoop/appcache/application_1556007841411_0001/container_1556007841411_0001_02_000002/pyspark.zip/pyspark/daemon.py", line 73, in worker File "/mnt/yarn/usercache/hadoop/appcache/application_1556007841411_0001/container_1556007841411_0001_02_000002/pyspark.zip/pyspark/worker.py", line 397, in main if read_int(infile) == SpecialLengths.END_OF_STREAM: File "/mnt/yarn/usercache/hadoop/appcache/application_1556007841411_0001/container_1556007841411_0001_02_000002/pyspark.zip/pyspark/serializers.py", line 714, in read_int raise EOFError EOFError 19/04/23 08:35:41 ERROR Executor: Exception in task 1.3 in stage 0.0 (TID 5) java.io.EOFException: Unexpected end of input stream
出现不完整gz文件的原因在于gzip压缩成.gz文件并不是原子操作。 在压缩初始的时候就会生成.gz文件,所以依赖.gz这个文件的生成不可靠的。
如果在确保.gz完全压缩完成呢?一开始我觉得可以在 `postrotate` 这里增加DONE(标记)文件 然而实际这种方式并不work, 因为我理解错了logrotate的执行顺序。 通过我这几次实验+阅读文档,这个logrotate的顺序应该是
- 先对所有的log文件重新命名
- 对历史数据进行轮转
- 调用 `nginx reopen_logs`
- 对这些新生成的文件压缩成.gz文件
所以 `postrotate` 是在压缩成.gz文件就执行了,并不能满足我的需求。
查阅了logrotate的文档之后,发现有个 `lastaction` block. 这个区域内部的代码是在 所有动作完成之后执行的,正好可以满足我的需求。所以一个nginx比较好的logrotate配置应该是这样的
[ec2-user@rpc_ngx nginx-logs]# cat /etc/logrotate.d/nginx /var/log/nginx/*log { create 0664 nginx root daily rotate 10 missingok compress notifempty sharedscripts postrotate /etc/init.d/nginx reopen_logs endscript lastaction echo /var/log/nginx/*log-$(date +%Y%m%d).gz | sed -e 's/.gz/.gz.done/g' | xargs touch endscript }