nginx日志切割shell脚本

一、脚本思路

第一步就是重命名日志文件,不用担心重命名后nginx找不到日志文件而丢失日志。在你未重新打开原名字的日志文件前,nginx还是会向你重命名的文件写日志,linux是靠文件描述符而不是文件名定位文件。

第二步向nginx主进程发送USR1信号。

nginx主进程接到信号后会从配置文件中读取日志文件名称,重新打开日志文件(以配置文件中的日志名称命名),并以工作进程的用户作为日志文件的所有者。

重新打开日志文件后,nginx主进程会关闭重名的日志文件并通知工作进程使用新打开的日志文件。

工作进程立刻打开新的日志文件并关闭重名名的日志文件。

然后你就可以处理旧的日志文件了。

二、脚本实现

nginx日志按日期自动切割脚本如下:

#nginx日志切割脚本

#!/bin/bash
#设置日志文件存放目录
logs_path="/usr/local/nginx/logs/"
#设置pid文件
pid_path="/usr/local/nginx/nginx.pid"

#重命名日志文件
mv ${logs_path}access.log ${logs_path}access_$(date -d "yesterday" +"%Y%m%d").log

#向nginx主进程发信号重新打开日志
kill -USR1 `cat ${pid_path}`

试验环境:

# cat /etc/redhat-release 
Red Hat Enterprise Linux Server release 5.3 (Tikanga)

# /opt/nginx/nginx -v
nginx version: nginx/1.6.2

代码:

#!/bin/bash
# ==============================================================================
# chmod u+x /opt/nginx/cut_nginx_log.sh
# crontab -e
# 0 0 * * * /opt/nginx/cut_nginx_log.sh > /opt/nginx/logs/cut_nginx_log.log 2>&1
# ==============================================================================

LOGS_PATH="/opt/nginx/logs"
ARCHIVE_YEAR=$(date -d "yesterday" "+%Y")
ARCHIVE_MONTH=$(date -d "yesterday" "+%m")
ARCHIVE_DATE=$(date -d "yesterday" "+%Y%m%d_%H%M%S")
if [ -r /opt/nginx/nginx.pid ]; then
  mkdir -p "${LOGS_PATH}/${ARCHIVE_YEAR}/${ARCHIVE_MONTH}"
  mv "${LOGS_PATH}/access.log" "${LOGS_PATH}/${ARCHIVE_YEAR}/${ARCHIVE_MONTH}/access_${ARCHIVE_DATE}.log"
  kill -USR1 $(cat "/opt/nginx/nginx.pid")
  sleep 1
  gzip "${LOGS_PATH}/${ARCHIVE_YEAR}/${ARCHIVE_MONTH}/access_${ARCHIVE_DATE}.log"
else
  echo "Nginx might be down"
fi

# ==============================================================================
# Clean up log files older than 100 days
# ==============================================================================

# Change HOUSEKEEPING=1 to enable clean up
HOUSEKEEPING=0
KEEP_DAYS=100
if [ $HOUSEKEEPING == 1 ]; then
  if [ -d "${LOGS_PATH}" ]; then
    find "${LOGS_PATH}" -type f -name "access_*.log.gz" -mtime +${KEEP_DAYS} -exec rm -f {} ;
  fi
fi

参考:
http://wiki.nginx.org/LogRotation

保存以上脚本nginx_log.sh,并设置定时切割任务

三、定时工作

在crontab中设置作业

0 0 * * * bash /usr/local/nginx/nginx_log.sh

这样就每天的0点0分把nginx日志重命名为日期格式,并重新生成今天的新日志文件。

利用Nginx的auth_basic模块密码保护WordPress后台目录

有时候WordPress会遭遇到一些别有用心的人尝试访问wp-admin进行登录,这时候如果对后台目录的访问进行一个限制,就能防止一部分恶意行为。那么今天就利用一下Ngnix的ngx_http_auth_basic_module模块,进行一个简单的访问验证。

默认情况下Nginx已经安装编译了这个模块,我们可以通过几步就可以完成对指定目录的保护。

第一步:创建密码文件

登录ssh到你想要存放密码文件的目录,用Vi建立文本( 按 i 插入模式 :wq 保存并退出)

格式为 用户名:密码

建立完成后,记得设置一下文件权限为400

[root@izyi5 www]# vi my.pass
test:123456
~
:wq
[root@izyi5 www]#chmod 400 my.pass

第二步:修改Nginx配置

仿照下面代码修改站点的Nginx配置文件

server{
server_name  www.blog67.com blog67.com;

index index.html index.php;
root /data/site/www.blog67.com;

#添加auth_basic验证代码
#location后为需要保护的目录路径,此处以WP后台为例
#auth_basic为提示文本
#auth_basic_user_file为密码文件路径

location /wp-admin/
{
auth_basic "Test For blog67.com";
auth_basic_user_file /www/my.pass;
}

}

注意:密码文件路径一定要正确,否则会一直出现403错误

然后重载Nginx配置,执行

nginx -s reload

效果

现在可以访问一下后台看看,出现下图:

未分类

成功~

Nginx报No input file specified错误解决方法

由于某些原因,服务器重启了,然而重启之后,再次访问居然报404错了:No input file specified.nginx配置没有动过,怎么会无缘无故出现这个问题呢?

这个其实是很常见的错误,百度随便一搜就有好多的答案,解决问题的方案都是重新配置nginx,使它能正确找到php文件。这个也是我早就知道的,既然发了这篇文章,就说明用那些方法不能解决,或者就不是nginx配置方面的问题。那么还有什么原因造成这个现象呢?

nginx做了虚拟主机配置,访问其他的站点,更奇怪的是有些可以访问,有些也报404.总结了下规律,发现如果index到html等静态文件,就没有问题,如果index到php文件,那就不行了。

不知道什么原因的话,那就控制变量一步一步来吧。

首先在根目录下建一个文件:a.php,写个简单的输出hello world的程序。

<?php

echo "hello world" ;

然后试着访问下https://chenqinghe.com/a.php。不行,还是报404.

再建个文件:1.txt,随便打些内容,再次访问。正常返回了!

这就奇怪了,nginx配置没有改过,肯定是能够找到php文件的,那为什么还不行呢?

又搜了下,发现了这篇文章:Nginx报 No input file specified. 的问题解决之路(https://m.aliyun.com/yunqi/articles/34240)

我立马看了下根目录下面有没有.user.ini文件,让人失望的是,没有发现……

无奈之下想到了杀手锏strace,之前用来追踪mysql长连接时用过,可以看进程的系统调用。那用strace追踪一下看看咯,设置php-fpm为静态模式,子进程数量固定为1,然后用strace追踪这个子进程,然后访问网址,观察调用情况。

sudo strace -p 2773 -s 1000 //绑定pid为2773的进程,设置字符串长度为1000

然后发现了些猫腻:

未分类

原来是open_basedir捣的鬼!!这个php.ini中的设置会把打开文件目录限定在设置的目录内,如上图红框内所示,不在这个目录里,就不允许访问,所以会报这个错。在php.ini中把这项注释了之后,正常了!

那么为什么重启服务器之后会这样呢?后来仔细想想,之前在用/dev/urandom生成真随机数的时候设置的,那时候设置完了之后只在命令行下执行了php的命令,也就是只用了cli这个sapi,并没有重启php-fpm,所以当时没有发现这个问题,这次重启服务器之后,这个问题就暴露了出来,果然是个大坑啊……

这篇文章主要记录了排查错误的方式,更多的时候这些排查方式比解决方案更有用,所以记录下来。

配置nginx支持TLS 1.3

几个月前,我在升级本博客所用 Nginx 时,顺手加上了对 TLS 1.3 的支持,本文贴出详细的步骤和注意事项。有关 TLS 1.3 的介绍可以看 CloudFlare 的这篇文章:An overview of TLS 1.3 and Q&A。需要注意目前 Chrome 和 Firefox 支持的是 TLS 1.3 draft 18,暂时不要用在生产环境。

安装依赖

我的 VPS 系统是 Ubuntu 16.04.3 LTS,如果你使用其它发行版,与包管理有关的命令请自行调整。

首先安装依赖库和编译要用到的工具:

sudo apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev unzip git

获取必要组件

nginx-ct 和 ngx-brotli 与本文主题无关,不过都是常用的 Nginx 组件,一并记录在这里。

nginx-ct

nginx-ct 模块用于启用 Certificate Transparency 功能。直接从 github 上获取源码:

wget -O nginx-ct.zip -c https://github.com/grahamedgecombe/nginx-ct/archive/v1.3.2.zip
unzip nginx-ct.zip

ngx_brotli

本站支持 Google 开发的 Brotli 压缩格式,它通过内置分析大量网页得出的字典,实现了更高的压缩比率,同时几乎不影响压缩 / 解压速度。
以下是让 Nginx 支持 Brotli 所需准备工作,这些工作是一次性的。首先安装 libbrotli:

sudo apt-get install autoconf libtool automake

git clone https://github.com/bagder/libbrotli
cd libbrotli

# 如果提示 error: C source seen but 'CC' is undefined,可以在 configure.ac 最后加上 AC_PROG_CC
./autogen.sh

./configure
make
sudo make install

cd  ../

默认 libbrotli 装在 /usr/local/lib/libbrotlienc.so.1,如果后续启动 Nginx 时提示找不到这个文件,那么可以把它软链到 /lib 或者 /usr/lib 目录。如果还有问题,请参考这篇文章查找解决方案。

接下来获取 ngx_brotli 源码:

git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli

git submodule update --init

cd ../

OpenSSL

为了支持 TLS 1.3,需要使用 OpenSSL 1.1.1 的 draft-18 分支:

git clone -b tls1.3-draft-18 --single-branch https://github.com/openssl/openssl.git openssl

编译并安装 Nginx

接着就可以获取 Nginx 源码,编译并安装:

wget -c https://nginx.org/download/nginx-1.13.3.tar.gz
tar zxf nginx-1.13.3.tar.gz

cd nginx-1.13.3/

./configure --add-module=../ngx_brotli --add-module=../nginx-ct-1.3.2 --with-openssl=../openssl --with-openssl-opt='enable-tls1_3 enable-weak-ssl-ciphers' --with-http_v2_module --with-http_ssl_module --with-http_gzip_static_module

make
sudo make install

enable-tls1_3 是让 OpenSSL 支持 TLS 1.3 的关键选项;而 enable-weak-ssl-ciphers 的作用是让 OpenSSL 继续支持 3DES 等不安全的 Cipher Suite,如果你打算继续支持 IE8,才需要加上这个选项。

除了 http_v2 和 http_ssl 这两个 HTTP/2 必备模块之外,我还额外启用了 http_gzip_static,需要启用哪些模块需要根据自己实际情况来决定。
以上步骤会把 Nginx 装到 /usr/local/nginx/ 目录,如需更改路径可以在 configure 时指定。

WEB 站点配置

在 Nginx 的站点配置中,以下两个参数需要修改:

ssl_protocols              TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # 增加 TLSv1.3
ssl_ciphers                TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;

包含 TLS13 是 TLS 1.3 新增的 Cipher Suite,加在最前面即可;如果你不打算继续支持 IE8,可以去掉包含 3DES 的 Cipher Suite。

本博客完整的 Nginx 配置,请打开 (https://imququ.com/post/my-nginx-conf.html) 查看。

验证是否支持 TLS 1.3

目前最新版 Chrome 和 Firefox 都支持 TLS 1.3,但需要手动开启:

  • Chrome,将 chrome://flags/ 中的 Maximum TLS version enabled 改为 TLS 1.3(Chrome 62 中需要将 TLS 1.3 改为 Enabled (Draft),感谢 @TsuranSonoda 指出);

  • Firefox,将 about:config 中的 security.tls.version.max 改为 4;

本博客多次推荐的 Qualys SSL Labs’s SSL Server Test(https://www.ssllabs.com/ssltest/index.html) 也支持验证服务端是否支持 TLS 1.3,非常方便,继续推荐。

设置tomcat nginx上传文件大小限制

一、关于在tomcat在server.xml的配置文件上传大小20M的限制 – maxPostSize=”20971520″

<Connector port="8080" protocol="HTTP/1.1"
                           maxThreads="200" 
                           minSpareThreads="25" 
                           maxSpareThreads="100"
                           acceptCount="200"
                           maxPostSize="20971520"
                           connectionTimeout="30000"
                           enableLookups="false"
                           disableUploadTimeout="true"
                           compression="on"
                           compressableMimeType="text/html,text/xml,text/plain,text/css,
                           text/javascript,text/json,application/x-javascript,
                           application/javascript,application/json"
                       noCompressionUserAgents="gozilla, traviata"
               redirectPort="8443" />

二、在nginx的nginx.conf的配置文件上传大小为20M – client_max_body_size 20m;

location /gw/file/upload {
            proxy_pass http://127.0.0.1/upload;
            proxy_redirect  off;
            proxy_set_header        Host    $http_host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   Cookie $http_cookie;
            client_max_body_size   20m;
}

使用nginx virtualenv uWSGI配置django运行环境

升级并安装 pip

sudo apt-get update
sudo apt-get install python-pip

安装虚拟环境

sudo pip install virtualenv virtualenvwrapper

加入到环境变量中

当前用户目录下的 Env为虚拟环境存放的目录

echo "export WORKON_HOME=~/Env" >> ~/.bashrc
echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.bashrc

激活配置

source ~/.bashrc

创建虚拟环境

环境名为:firstsite

在用户当前目录下创建 Django工程

cd ~
django-admin.py startproject firstsite

django 的初始化

cd ~/firstsite
./manage.py migrate
./manage.py createsuperuser

Django静态文件配置

nano firstsite/settings.py
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
./manage.py collectstatic

安装 uWSGI

sudo apt-get install python-dev
sudo pip install uwsgi

测试是否能够正常访问 django 项目

  • http 指定进程端口8080
  • home指定虚拟环境目录
  • chdir指定 项目工程所在目录
uwsgi --http :8080 --home /home/pi/Env/firstsite --chdir /home/pi/firstsite -w firstsite.wsgi

创建 uwsgi 的配置文件

sudo mkdir -p /etc/uwsgi/sites
cd /etc/uwsgi/sites

uwsgi 的配置相关内容(重点)

[uwsgi]
project = firstsite
base = /home/pi

chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

master = true
processes = 5

socket = %(base)/%(project)/%(project).sock
chmod-socket = 666
vacuum = true

启动守护进程

vim /etc/systemd/system/uwsgi.service

[Unit]
Description=uWSGI Emperor service
After=syslog.target

[Service]
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target

重载守护进程的配置信息

sudo systemctl daemon-reload

系统重启后uwsgi守护进程自动重启

sudo systemctl enable uwsgi

启动uwsgi进程

sudo systemctl start uwsgi

nginx 的安装

sudo apt-get install nginx

nginx的配置

sudo nano /etc/nginx/sites-available/firstsite
server {
    listen 80;
    server_name firstsite.com www.firstsite.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/pi/firstsite;
    }

    location / {
        include         uwsgi_params;
        uwsgi_pass      unix:/home/pi/firstsite/firstsite.sock;
    }
}

nginx配置生效

sudo ln -s /etc/nginx/sites-available/firstsite /etc/nginx/sites-enabled

检查配置

sudo service nginx configtest

重启nginx

sudo service nginx restart

非 debug 模式

非 debug 模式需要重启uwsgi 服务

sudo systemctl restart uwsgi

Nginx自定义404页面3种方法

未分类

一个网站项目,肯定是避免不了404页面的,通常使用Nginx作为Web服务器时,有以下集中配置方式,一起来看看。

第一种:Nginx自己的错误页面

Nginx访问一个静态的html 页面,当这个页面没有的时候,Nginx抛出404,那么如何返回给客户端404呢?

看下面的配置,这种情况下不需要修改任何参数,就能实现这个功能。

server {

listen      80;

server_name  www.test.com;

root   /var/www/test;

index  index.html index.htm;

location / {

}

# 定义错误页面码,如果出现相应的错误页面码,转发到那里。

error_page  404 403 500 502 503 504  /404.html;

# 承接上面的location。

location = /404.html {

# 放错误页面的目录路径。

root   /usr/share/nginx/html;

}

}

第二种:反向代理的错误页面

如果后台Tomcat处理报错抛出404,想把这个状态叫Nginx反馈给客户端或者重定向到某个连接,配置如下:

upstream www {

server 192.168.1.201:7777  weight=20 max_fails=2 fail_timeout=30s;

ip_hash;

}

server {

listen       80;

server_name www.test.com;

root   /var/www/test;

index  index.html index.htm;



location / {

if ($request_uri ~* ‘^/$’) {

rewrite .*   http://www.test.com/index.html redirect;

}

# 关键参数:这个变量开启后,我们才能自定义错误页面,当后端返回404,nginx拦截错误定义错误页面

proxy_intercept_errors on;

proxy_pass      http://www;

proxy_set_header HOST   $host;

proxy_set_header X-Real-IP      $remote_addr;

proxy_set_header X-Forwarded-FOR $proxy_add_x_forwarded_for;

}

error_page    404  /404.html;

location = /404.html {

root   /usr/share/nginx/html;

}

}

第三种:Nginx解析php代码的错误页面

如果后端是php解析的,需要加一个变量

在http段中加一个变量 fastcgi_intercept_errors on 就可以了。

指定一个错误页面:

error_page    404  /404.html;

location = /404.html {

root   /usr/share/nginx/html;

}

指定一个url地址:

error_page 404  /404.html;

error_page 404 = http://www.test.com/error.html;

Typecho Nginx 开启https(解决其他页面404问题)

本文假设你已经申请好了证书,并已经配置到服务器

1、在项目根目录下的配置文件config.inc.php中添加如下代码,让后台访问https资源,不加的话后台登录仍然访问http;

define('__TYPECHO_SECURE__',true);

2、nginx配置文件中,在你解析443端口的server中,在localhost中添加如下代码,地址带参数跳转,不加会导致其他页面404;

try_files $uri $uri/ /index.php?$query_string;
if (!-e $request_filename){  
    rewrite ^/(.*) /index.php last;  
} 

例如:

location ~ .*.php(/.*)*$ {
    try_files $uri $uri/ /index.php?$query_string;
    if (!-e $request_filename){
        rewrite ^/(.*) /index.php last;
    }
   ...
}

3、在项目代码中header.php中加入如下代码,默认访问https(可选);

if ($_SERVER["HTTPS"] <> "on")
{
    $xredir = "https://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
    header("Location: ".$xredir);
}

有哪些Linux命令行的软件堪称神器?

ag:比grep、ack更快的递归搜索文件内容。

未分类

tig:字符模式下交互查看git项目,可以替代git命令。

未分类

mycli:mysql客户端,支持语法高亮和命令补全,效果类似ipython,可以替代mysql命令。

未分类

jq: json文件处理以及格式化显示,支持高亮,可以替换python -m json.tool。

未分类

shellcheck:shell脚本静态检查工具,能够识别语法错误以及不规范的写法。

未分类

yapf:Google开发的python代码格式规范化工具,支持pep8以及Google代码风格。

mosh:基于UDP的终端连接,可以替代ssh,连接更稳定,即使IP变了,也能自动重连。

fzf:命令行下模糊搜索工具,能够交互式智能搜索并选取文件或者内容,配合终端ctrl-r历史命令搜索简直完美。

未分类

PathPicker(fpp):在命令行输出中自动识别目录和文件,支持交互式,配合git非常有用。运行以下命令:

git diff HEAD~8 --stat | fpp

未分类

htop: 提供更美观、更方便的进程监控工具,替代top命令。

未分类

axel:多线程下载工具,下载文件时可以替代curl、

wget。axel -n 20 http://centos.ustc.edu.cn/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1511.iso

未分类

sz/rz:交互式文件传输,在多重跳板机下传输文件非常好用,不用一级一级传输。

cloc:代码统计工具,能够统计代码的空行数、注释行、编程语言。

未分类

ccache:高速C/C++编译缓存工具,反复编译内核非常有用。使用起来也非常方便:

gcc foo.c

改成:

ccache gcc foo.c

tmux:终端复用工具,替代screen、nohup。

未分类

neovim: 替代vim。

script/scriptreplay: 终端会话录制。

script -t 2>time.txt session.typescript # 录制开始
# your commands
exit # 录制结束

回放:

scriptreplay -t time.txt session.typescript

you-get: 非常强大的媒体下载工具,支持youtube、google+、优酷、芒果TV、腾讯视频、秒拍等视频下载。还有mac专有的pbcopy/pbpaste:

把命令行输出拷贝到系统粘贴板:

cat test.sh| pbcopy

把系统粘贴板内容拷到终端:pbpaste

mac下的say命令支持多种语言(英语、普通话、粤语)文本朗读,支持各种销魂恐怖的语气。跑这个命令感受下,小心被吓着了:

for i in `say -v '?' | cut -d ' ' -f 1`; do echo $i && say -v "$i" 'Hello World';done