wp 终极优化

wp 终极优化指的是通过使用PHP7.4+Memcached+OPcache+Mysql8+WP-Rocekt+nginx+阿里云cdn+阿里oss+WpJAM_Basic插件加速网站,提高网站性能。


开发环境搭建

在 Linux 服务器上安装php7+mysql+nginx+memcache+opcache

安装 php7.4.5

  • 安装依赖包
yum -y install php-gd php-bcmath php-mbstring php-xml curl curl-devel libcurl-devel net-snmp net-snmp-devel libxml2 \
libxml2-devel openssl-devel ncurses-devel zlib-devel  pcre-devel libevent-devel\
gd-devel  libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel  libmcrypt-devel mhash sqlite-devel oniguruma-devel
  • 下载并安装 php
wget https://www.php.net/distributions/php-7.4.5.tar.gz
tar -zxvf php-7.4.5.tar.gz
cd php-7.4.5

./buildconf

./configure --prefix=/usr/local/php7 --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d    --enable-fpm \
--with-fpm-user=nginx --with-fpm-group=nginx   \
--with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd   --with-mysql-sock=/tmp/mysql.sock  \
 --with-libdir=lib64   --enable-gd --with-jpeg --with-freetype  \
--with-zlib=/usr   --with-openssl=/usr  --with-mhash  --enable-bcmath  --enable-mbstring  \
--enable-xml  --enable-opcache   --enable-sockets --with-gettext --enable-session --with-curl --enable-ctype

sudo make -j 2 && sudo make install

Memcached 安装

需要安装 memcached 服务端和 php 的 memcached 扩展.

安装 memcached 服务端

sudo yum -y install libevent libevent-devel
wget http://www.memcached.org/files/memcached-1.6.5.tar.gz

tar xzvf memcached-1.6.5.tar.gz
cd memcached-1.6.5
./configure --prefix=/usr/local/memcached
sudo make && sudo make install
sudo ln -s /usr/local/memcached/bin/memcached /usr/bin/memcached
sudo cp ~/src/memcached-server/memcached-1.6.5/memcached.sysv  /etc/init.d/memcached
sudo chmod +x /etc/init.d/memcached
sudo service memcached start
sudo chkconfig --add memcached
sudo chkconfig memcached on

安装 php 的 memcached 扩展

  • 安装 libmemcached

sudo yum -y install cyrus-sasl-devel # 让 memcached 支持用户名和密码

wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz

./configure --with-memcached=/usr/local/memcached --prefix=/usr/local/libmemcached

sudo make && sudo make install

  • 安装 php 的 memcached 扩展
sudo yum -y install autoconf cyrus-sasl-devel
wget https://pecl.php.net/get/memcached-3.1.5.tgz
tar -zxvf memcached-3.1.5.tgz
cd memcached-3.1.5
/usr/local/php7/bin/phpize       # 改为phpize的实际位置,下面的php-config路径也是
./configure --with-libmemcached-dir=/usr/local/libmemcached --with-php-config=/usr/local/php7/bin/php-config
sudo make && sudo make install

查看是否生效: /usr/local/php7/bin/php -m | grep memcached

下面这段是针对wordpress优化的:

另外利用 Memcached 加速 wp,还需要下载插件,去Memcached下载插件,

下载好后,将此插件放到wp-content目录.

注意

一定要放在此目录,不能放到 plugins 目录,wp 会自动检测此目录有没有 memcached,有则启用。

查看 memcached 的命中率可通过telnet 127.0.0.1 11211然后输入stats可查看.

OPcache 配置

在编译 php7 时添加参数--enable-opcache即可安装 opcache

编辑php.ini 中,添加如下内容:

[Zend Opcache]
zend_extension=opcache.so   # 加载opcache扩展文件
opcache.enable=1     # 开启opcache
opcache.memory_consumption=128   # 共享内存的大小, 总共能够存储多少预编译的 PHP 代码(单位:MB),推荐128M(根据服务器内存大小调整)
opcache.interned_strings_buffer=8  # 暂存池中字符串的占内存总量.(单位:MB), 推荐 8
opcache.max_accelerated_files=4000  # 最大缓存的文件数目 200 到 100000 之间,推荐 4000
opcache.revalidate_freq=60  # 默认是2s检查一次文件更新 注意:0是一直检查不是关闭,推荐 60-120
opcache.fast_shutdown=1   # 打开快速关闭, 打开这个在PHP Request Shutdown的时候会收内存的速度会提高
opcache.enable_cli=1

具体可查看 LNMP 的 opcache.sh 脚本。

查看是否安装成功可通过 PHP -V 会有 zend 字样显示及成功

另可通过http://youIP/ocp.php查看,安装了 opcache 后会有此文件,默认是放在 default 下。

php-fpm 配置

sudo vim /usr/local/php7/etc/php-fpm.d/www.conf

添加如下内容:

user = nginx
group = nginx
pm.max_children = 500
php-fpm初始/空闲/最大worker进程数,根据服务器内存来定,基本上每个进程占20-30m内存,自己按照内存大小计算合理数字。
pm.start_servers = 10
pm.min_spare_servers = 7
pm.max_spare_servers = 10
# 最大处理请求数是指一个php-fpm的worker进程在处理多少个请求后就终止掉,master进程会重新respawn一个新的,这个配置的主要目的是避免php解释器或程序引用的第三方库造成的内存泄露。
pm.max_requests = 3000
最大执行时间在php.ini和php-fpm.conf里都可以配置,配置项分别为max_execution_time和request_terminate_timeout,建议设置300秒。

php-fpm 启动项

sudo vim /etc/init.d/php-fpm

修改如下内容:

#prefix=@prefix@
#exec_prefix=@exec_prefix@

#php_fpm_BIN=@sbindir@/php-fpm
#php_fpm_CONF=@sysconfdir@/php-fpm.conf
#php_fpm_PID=@localstatedir@/run/php-fpm.pid
prefix=/usr/local/php7
php_fpm_BIN=/usr/local/php7/sbin/php-fpm
php_fpm_CONF=/usr/local/php7/etc/php-fpm.conf
php_fpm_PID=/usr/local/php7/var/run/php-fpm.pid

详细的 php-fpm 请参考: PHP-FPM 安装与配置

注意

上述 php-fpm 文件也可去PHP-FPM 官方下载地址下载

php-fpm 命令

启动: sudo /usr/local/php-7.3.8/sbin/php-fpm或者sudo /etc/init.d/php-fpm start

关闭: sudo kill -INT pid(php-fpm master进程号)

重启: sudo kill -USR2 pid(php-fpm master进程号)或者sudo /etc/init.d/php-fpm restart

警告

/etc/init.d/下自定义脚本全部设置权限 700

  • php-fpm 启动报错:

报错信息: NOTICE: PHP message: PHP Warning: PHP Startup: Unable to load dynamic library 'curl.so'

类似的错误大概有 18 个。

解决办法:

/etc/php.d/*.ini文件里面的extension=这一行全部注释即可.

然后用sudo /usr/local/php-7.3.8/bin/php -m查看加载的模块.

php 7自动化配置脚本

此脚本主要是自动配置 php.ini:

#!/bin/bash

php_install_dir=/usr/local/php7
cp php.ini-production $php_install_dir/etc/php.ini
Mem=`free -m | awk '/Mem:/{print $2}'`
if [ $Mem -gt 1024 -a $Mem -le 1500 ];then
    Memory_limit=192
elif [ $Mem -gt 1500 -a $Mem -le 3500 ];then
    Memory_limit=256
elif [ $Mem -gt 3500 -a $Mem -le 4500 ];then
    Memory_limit=320
elif [ $Mem -gt 4500 ];then
    Memory_limit=448
else
    Memory_limit=128
fi
sed -i "s@^memory_limit.*@memory_limit = ${Memory_limit}M@" $php_install_dir/etc/php.ini
sed -i 's@^output_buffering =@output_buffering = On\noutput_buffering =@' $php_install_dir/etc/php.ini
sed -i 's@^;cgi.fix_pathinfo.*@cgi.fix_pathinfo=0@' $php_install_dir/etc/php.ini
sed -i 's@^short_open_tag = Off@short_open_tag = On@' $php_install_dir/etc/php.ini
sed -i 's@^expose_php = On@expose_php = Off@' $php_install_dir/etc/php.ini
sed -i 's@^request_order.*@request_order = "CGP"@' $php_install_dir/etc/php.ini
sed -i 's@^;date.timezone.*@date.timezone = Asia/Shanghai@' $php_install_dir/etc/php.ini
sed -i 's@^post_max_size.*@post_max_size = 50M@' $php_install_dir/etc/php.ini
sed -i 's@^upload_max_filesize.*@upload_max_filesize = 50M@' $php_install_dir/etc/php.ini
sed -i 's@^;upload_tmp_dir.*@upload_tmp_dir = /tmp@' $php_install_dir/etc/php.ini
sed -i 's@^max_execution_time.*@max_execution_time = 600@' $php_install_dir/etc/php.ini
sed -i 's@^;realpath_cache_size.*@realpath_cache_size = 2M@' $php_install_dir/etc/php.ini
sed -i 's@^disable_functions.*@disable_functions = passthru,exec,system,chroot,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket,popen@' $php_install_dir/etc/php.ini
sed -i 's@^session.cookie_httponly.*@session.cookie_httponly = 1@' $php_install_dir/etc/php.ini
sed -i 's@^mysqlnd.collect_memory_statistics.*@mysqlnd.collect_memory_statistics = On@' $php_install_dir/etc/php.ini
[ -e /usr/sbin/sendmail ] && sed -i 's@^;sendmail_path.*@sendmail_path = /usr/sbin/sendmail -t -i@' $php_install_dir/etc/php.ini
#如果编译时去掉了 --enable-opcache,则以下包含opcache的都请忽略
sed -i 's@^\[opcache\]@[opcache]\nzend_extension=opcache.so@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.enable=.*@opcache.enable=1@' $php_install_dir/etc/php.ini
sed -i "s@^;opcache.memory_consumption.*@opcache.memory_consumption=$Memory_limit@" $php_install_dir/etc/php.ini
sed -i 's@^;opcache.interned_strings_buffer.*@opcache.interned_strings_buffer=8@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.max_accelerated_files.*@opcache.max_accelerated_files=4000@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.revalidate_freq.*@opcache.revalidate_freq=60@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.save_comments.*@opcache.save_comments=0@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.fast_shutdown.*@opcache.fast_shutdown=1@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.validate_timestamps.*@opcache.validate_timestamps=1@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.enable_cli.*@opcache.enable_cli=1@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.use_cwd.*@opcache.use_cwd=1@' $php_install_dir/etc/php.ini
sed -i 's@^opcache.max_accelerated_files.*@opcache.max_accelerated_files=100000@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.max_wasted_percentage.*@opcache.max_wasted_percentage=5@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.consistency_checks.*@opcache.consistency_checks=0@' $php_install_dir/etc/php.ini
sed -i 's@^;opcache.optimization_level.*@;opcache.optimization_level=0@' $php_install_dir/etc/php.ini

mysql 开启 query cache

show variables like 'have_query_cache';  # 查看mysql版本是否支持查询缓存
show variables like '%query_cache%';     # 查看是否开启了查询缓存
  • 开启查询缓存:

在 my.cnf 中[mysqld]添加:

query_cache_size=128M

query_cache_type=1

然后重启 mysql

安装与配置 nginx

sudo yum install yum-utils

sudo vim /etc/yum.repos.d/nginx.repo

添加:

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

启用 nginx 源

sudo yum-config-manager --enable nginx-mainline

安装 nginx

sudo yum install nginx

开机启动 nginx

systemctl enable nginx

nginx 开机启动

通过上面的操作就自动将 nginx 开机启动了,所以下面的操作可不用执行:

sudo vim /usr/lib/systemd/system/nginx.service

添加:

[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

开机启动 nginx: sudo systemctl enable nginx

配置 nginx

下面贴上完整的 nginx.conf 配置文件:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
worker_rlimit_nofile 65535;

events {
    use epoll;
    worker_connections 65535;
    multi_accept on;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    server_names_hash_bucket_size 128;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    client_max_body_size 50m;

    sendfile   on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    #fastcgi_intercept_errors on;
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 256k;

    gzip on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 4;
    gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss;
    gzip_vary on;
    gzip_proxied   expired no-cache no-store private auth;
    gzip_disable   "MSIE [1-6]\.";

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

    include /etc/nginx/conf.d/default.conf;
}

下面的是虚拟主机配置文件内容:

server {
    listen 80;
    server_name api.echoxu.cn;
    rewrite ^/(.*)$ https://api.echoxu.cn/$1 permanent;
}

server {
    listen 443 ssl;
    server_name  api.echoxu.cn;
    root /usr/share/nginx/html/iweb;
    index index.php index.html index.htm;

    ssl_certificate /etc/nginx/ssl/api.echoxu.cn.pem;
    ssl_certificate_key /etc/nginx/ssl/api.echoxu.cn.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    access_log /usr/share/nginx/logs/Access.log;
    error_log /usr/share/nginx/logs/Error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~* \.php$ {
        root      /usr/share/nginx/html/iweb;
        fastcgi_index   index.php;
        fastcgi_pass    127.0.0.1:9000;
        include         fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location = /xmlrpc.php {
        deny all;
        access_log off;
        log_not_found off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location ~ /\. {
        deny all;
    }

    location ~* \.(sh|docx|txt|doc|php|php5|pl|py|zip|gz|bx|)$ {
         deny all;
    }

    location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires 30d;
        log_not_found off;
    }
}

WP-Rocek 安装及配置

先设置固定链接: https://dev.echoxu.cn/%postname%.html

其实都是一些常见的前端优化技巧,如: 压缩图片,合并文件,使用 CDN 等

下面是 wp-rocket3.3.5.2 版本的设置:

wwwechoxu

wwwechoxu

wwwechoxu

wwwechoxu

wwwechoxu

wwwechoxu

相同的插件还有wp-super-cache,实际使用下来 wp-rocket 的效果更好.

使用 WPJAM_Basic 插件优化

wwwechoxu

wwwechoxu

wwwechoxu

wordpress 使用 cdn 进行静态资源加速

wwwechoxu

wwwechoxu

阿里云 OSS 及 CDN 配置

加速 OSS 架构如下图所示:

wwwechoxu

CDN 加速 OSS 源站资源

阿里云对象存储 OSS 配置

操作过程:

1: 开通阿里云对象存储 OSS 服务

2: 去 OSS管理控制台---传输管理---域名管理 绑定一个自定义的域名,注意:此域名需备案,另外此项操作不用设置域名解析.

3: 去 OSS管理控制台---基础设置---镜像回源 添加一个规则,镜像回源指的是当访问 oss 里的文件不存在时就去源网站(你的网站域名)抓取并复制一份然后存储到 oss 存储空间里.

4: 去 OSS管理控制台---权限管理---跨域设置 创建一个规则,允许你的网站进行跨域访问.

5: 去 OSS管理控制台---权限管理---防盗链 添加规则,也可不设置

wwwechoxu

wwwechoxu

wwwechoxu

wwwechoxu

阿里云 CDN 配置

1: 去 CDN管理控制台---传输管理---域名管理---阿里云 CDN 加速 进行 cdn 加速配置,此操作需设置域名解析.

2: 去 CDN管理控制台---HTTPS配置---HTTPS证书 添加一个 ssl 证书,可申请一个免费的证书,等证书生成后直接点击部署---CDN 即可完成此项操作.

3: 去 CDN管理控制台---回源配置---回源HOST 设置当访问 CDN 不存在的文件时,应该去对象存储 oss 里获取文件,所以此处填写的是对象存储 oss 的域名,可以是阿里云对象存储 oss 提供的域名或者是你给 oss 绑定的域名.

4: 去 CDN管理控制台---回源配置---回源协议 选择协议为HTTPS

wwwechoxu

wwwechoxu

配置 HTTPS 证书

申请 ssl 证书时一直是"证书申请中"问题

验证静态文件是否使用 cdn 进行加速

1: 先通过dig cache.echoxu.cn 验证 oss 使用 cdn 加速是否配置正确,当出现cache.echoxu.cn.w.kunlunca.com即表示 oss 已经使用 cdn 加速了.

2: 查看 wordpress 网站源码,看静态文件是不是使用 cdn 域名cache.echoxu.cn进行访问.

wp 常见问题

安装插件时需要提供 ftp 账号信息

这是因为没有访问权限导致的,假如你使用的是 nginx,将你的 wp 主目录的属主设为 nginx 进程启动的用户名,且设置 wp 主目录权限为 755,文件权限为 644

sudo chown -R nginx用户名.root wp主目录

sudo chmod 755 wp主目录

如果还不行请在wp-config.php添加:

/** 绕过FTP验证*/
define(FS_METHOD, ‘direct’);
define(FS_CHMOD_DIR, 0777);
define(FS_CHMOD_FILE, 0777);

修改主题名

请尽量不要修改此项,做到尊重主题作者.

1: 将下载好的主题文件夹改名为你想好的名称.

2: 修改下载好的主题目录下的style.css里面的Theme Name即可.

wp 更换域名

假如你的域名由https://dev.echoxu.cn改为https://api.echoxu.cn,请替换下面的域名并在数据库中执行:

UPDATE iweb_options SET option_value = REPLACE(option_value, 'https://dev.echoxu.cn', 'https://api.echoxu.cn') WHERE option_name = 'home' OR option_name = 'siteurl';

UPDATE iweb_posts SET post_content = REPLACE (post_content, 'https://dev.echoxu.cn', 'https://api.echoxu.cn');

UPDATE iweb_postmeta SET meta_value = REPLACE (meta_value, 'https://dev.echoxu.cn','https://api.echoxu.cn');

UPDATE iweb_comments SET comment_content = REPLACE (comment_content, 'https://dev.echoxu.cn', 'https://api.echoxu.cn');

UPDATE iweb_comments SET comment_author_url = REPLACE (comment_author_url, 'https://dev.echoxu.cn','https://api.echoxu.cn');

UPDATE iweb_posts SET guid = REPLACE (guid, 'https://dev.echoxu.cn', 'https://api.echoxu.cn') WHERE post_type = 'attachment';

上面的 sql 可通过工具生成,更换域名 sql 生成器

更换数据库前缀

下面的 sql 是将数据库前缀由iweb_改为isite_

RENAME TABLE iweb_comments TO isite_comments;

RENAME TABLE iweb_commentmeta TO isite_commentmeta;

RENAME TABLE iweb_links TO isite_links;

RENAME TABLE iweb_options TO isite_options;

RENAME TABLE iweb_postmeta TO isite_postmeta;

RENAME TABLE iweb_posts TO isite_posts;

RENAME TABLE iweb_terms TO isite_terms;

RENAME TABLE iweb_termmeta TO isite_termmeta;

RENAME TABLE iweb_term_relationships TO isite_term_relationships;

RENAME TABLE iweb_term_taxonomy TO isite_term_taxonomy;

RENAME TABLE iweb_usermeta TO isite_usermeta;

RENAME TABLE iweb_users TO isite_users;

UPDATE isite_options SET option_name = REPLACE(option_name, 'iweb_', 'isite_') WHERE option_name LIKE 'iweb_%';

UPDATE isite_usermeta SET meta_key = REPLACE(meta_key, 'iweb_', 'isite_') WHERE meta_key LIKE 'iweb_%';

数据库前缀 sql 生成器

如何修改数据库前缀

轻松更改 WordPress 的数据库前缀

wp-admin/css/login.min.css中找到background-image:none,url(../images/wordpress-logo.svg?ver=20131107) 替换为你自定义的 logo 地址即可.

嫌麻烦可以直接替换wp-admin/images/wordpress-logo.svg为你的 logo,并重命名为wordpress-logo.svg

wp 后台慢

优化如下三项:

  • Google 字体

可用 vscode 打开下载好的 wp 文件,然后在 查看-搜索 然后输入 google 即可找到 wp 中使用 google   ajax 和 google fonts 服务的文件路径.在 wp5.4 中只有wp-includes/script-loader.php使用了 google 服务,可通过 vps 下载好 google   ajax 文件,然后将其放在自己的服务器上,最后修改wp-includes/script-loader.php里的 google 服务为本地路径即可.

  • Gravatar 头像

  • Emoji 图片

查看 wp 建立了多少查询

add_action( 'wp_footer', 'wpjam_page_speed' );
function wpjam_page_speed() {
  date_default_timezone_set( get_option( 'timezone_string' ) );
  $content  = '[ ' . date( 'Y-m-d H:i:s T' ) . ' ] ';
  $content .= '页面生成时间 ';
  $content .= timer_stop( $display = 0, $precision = 2 );
  $content .= ' 查询 ';
  $content .= get_num_queries();
  $content .= ' 次';
  if( ! current_user_can( 'administrator' ) ) $content = "<!-- $content -->";
  echo $content;
}

显示后台的远程请求

/**显示后台的远程请求*/
add_filter('pre_http_request', 'wpjam_admin_display_http_request', 10, 3);
function wpjam_admin_display_http_request($status, $r, $url){
    if(is_admin() && isset($_GET['debug'])){
        echo 'http_request:'.$url."\n<br />";
        return $status;
    }
}

注意该代码只能检测使用 WP_Http 方式实现的远程请求,如果插件作者直接使用 cURL 来实现的远程请求则无法打印出来。

附加一个小技巧,让后台的远程请求快速完成,比如 1 秒内必须完成:

/**让后台的远程请求在1s内快速完成*/
add_filter('http_request_timeout', 'wpjam_admin_short_http_request_timeout');
function wpjam_admin_short_http_request_timeout($timeout){
    if(is_admin()){
        return 1;
    }
    return $timeout;
}

wp 安全优化

wordpress 安全很重要,请确保做到如下:

wp 目录权限设置

按下图修改 wp 目录权限,不要设置目录权限为 777

wwwechoxu

数据库权限设置

数据库配置不要使用 root 账号,需要新建个账号,开放其只能对 wp 数据库进行增删改查,且其只能在本地操作,不能开放数据库端口.

# mysql8
CREATE DATABASE IF NOT EXISTS wpdata DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
CREATE USER IF NOT EXISTS 'wpdata'@'localhost' IDENTIFIED WITH mysql_native_password BY '数据库密码';
GRANT ALL ON isite.* TO 'wpdata'@'localhost';
FLUSH PRIVILEGES;

其他命令:

update mysql.user set host='localhost' where user='root';    # 修改root只能在本地登录
delete from mysql.user where user='test';      # 删除多余的用户
show grants for 'wpdata'@'localhost';     # 查看某个用户分配的权限

提示

wp-config.php 中数据库配置项改为非 root 以及只能本地登录,不要使用默认的数据库前缀

wp 登录界面跳转

使用过 wp 的人都知道 wp 的后台地址是域名+wp-admin,所以这样是非常不安全的.

现在我们可以通过如下代码对 wp 登录界面进行跳转:

/**
 * 修改后台登录地址
 */
add_action('login_enqueue_scripts','login_protection');
function login_protection(){
	if($_GET['iwantlogin'] != 'loginpara')
		header('Location: 你的域名');
}

这样当我们通过域名+wp-admin登录就会跳转到你的网站首页,只有通过https://域名/wp-login.php?iwantlogin=loginpara才能进行登录.

提示

if($_GET['iwantlogin'] != 'loginpara')里的 iwantloginloginpara 可改成自己喜欢的

wp 登录账号密码设置

不要使用 admin 作为登录账号,账号密码最好要用数字+字母+特殊符合组合

全站使用 https

使用 https 加密网站

关闭 XML-RPC

在当前主题的 functions.php 文件添加如下代码:

add_filter('xmlrpc_enabled', '__return_false');

当然也可利用 nginx 禁止所有 xmlrpc.php 请求

location = /xmlrpc.php {
 deny all;
 access_log off;
 log_not_found off;
}

这样你再通过https://网站域名/xmlrpc.php 访问就变成 403 了

安装的 wpjam-basic 插件已集成了此功能.

关闭注册功能

取消 设置-成员资格-任何人都可以注册 前面的对勾

定期更新 wp 版本和插件

使用旧的 wp 会有安全风险,尽量更新到最新的 wp 版本

提示

有关 wp 安全的插件有 hide my wp以及ithemes-security-pro

定期备份 wp 网站

可以使用BackupBuddy插件进行网站备份和迁移

封禁入侵 ip

打开 nginx 日志你会看到有很多进行破解的 ip,我们需要找到他们并封禁其 ip:

cat nginx.log | cut -d ' ' -f 1 | sort | uniq -c | awk '{if ($1 > 5) print $0}' | sort -nr | less > ip.txt

通过上面的命令我们找到了进行 5 次尝试破解的 ip 地址.下面我们对其 ip 进行封禁:

sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address="181.174.83.226" drop'
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address="129.213.59.142" drop'
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address="60.248.159.139" drop'

重启防火墙firewall-cmd --reload,可通过firewall-cmd --zone=public --list-rich-rules查看刚添加的规则.

如果发现误封了 ip,可通过sudo firewall-cmd --permanent --remove-rich-rule='rule family=ipv4 source address="181.174.83.226" drop'进行解封 ip。

下面是自动化封禁 ip 的脚本 (分析 Error.log 日志也能得到相同的效果) :

#!/bin/bash
# drop ip
# author: echoxu
# todo: 异步执行,提高运行效率

ip_lock_file=/root/ip_lock_file.txt

ip_arr=()

ip_limit_count=5

ip_from_firewall_rules=`firewall-cmd --zone=public --list-rich-rules |awk -F ' ' '{print $4}' |grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"`

ip_from_nginx_log=`cat /usr/share/nginx/logs/Access.log | awk -F ' ' '{if ($9 == 404 || $9 == 403 || $9 == 400) print $1}' | sort -rn  |uniq -c | awk -F ' ' '{if ($1 > $ip_limit_count) print $2}'`

ip_from_secure_log=`cat /var/log/secure-20231119 |grep -E 'Did not|Bad protocol' | grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"  |sort -u`





getIPFromFirewallRules(){
	for firewallip in $ip_from_firewall_rules 
    	do
            echo "$(date +'%F %T') 已封禁入侵ip: $firewallip " >> $ip_lock_file
    done
}


getIPFromNginxLog(){
    for nginxlogip in $ip_from_nginx_log
        do
            ip_arr[${#ip_arr[*]}]=${nginxlogip}
    done

     
    #echo "从 Nginx log 中获得 ${#ip_arr[*]} 个 ip,分别为:${ip_arr[*]}"
}


# kill ip from /var/log/secure
getIPFromSecureLog(){
    for securelogip in $ip_from_secure_log
        do
	        ip_arr[${#ip_arr[*]}]=${securelogip}
    done


    #echo "从 secure log 中获得 ${#ip_arr[*]} 个 ip,分别为:${ip_arr[*]}"
}


generateBaseData(){
    if [ ! -f $ip_lock_file ];then
        getIPFromFirewallRules      # 将 firewall rules 里的数据导入到 ip_lock_file (程序首次运行时执行此函数)
    fi
}


killIP(){
    for ip in ${ip_arr[*]}
        do
            ip_is_exist=`cat $ip_lock_file |grep $ip|wc -l`

            if [ $ip_is_exist -eq 0 ];then
                firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=$ip drop"
                echo "$(date +'%F %T') 已封禁入侵ip: $ip " >> $ip_lock_file
            fi
            
            #echo "入侵ip: $ip 已在黑名单中存在。 "
    done
}


main(){
    generateBaseData
    getIPFromNginxLog
    getIPFromSecureLog
    killIP
    firewall-cmd --reload
}


main

添加定时任务,让其每半小时执行一次脚本并封禁破解次数>7 的 ip 地址:

crontab -e 然后添加如下:

0 0 * * * /usr/sbin/logrotate -f /etc/logrotate.daily.0/nginx >/dev/null 2>&1

*/30 * * * * sh /root/killIP.sh > /dev/null 2>&1 &

最好对 nginx 的日志进行一些切割处理,让其每天产生一个日志:

sudo vim /etc/logrotate.daily.0/nginx

添加如下内容:

/usr/share/nginx/logs/*.log {
        daily
        missingok
        rotate 30
        compress
        dateext
        delaycompress
        notifempty
        create 640 root root
        sharedscripts
        postrotate
                if [ -f /var/run/nginx.pid ]; then
                        kill -USR1 `cat /var/run/nginx.pid`
                fi
        endscript
}

添加定时任务,每天 00:00 产生新的日志文件:

0 0 * * * /usr/sbin/logrotate -f /etc/logrotate.daily.0/nginx >/dev/null 2>&1

wp 软件优化

主要分为如下几类:

替换 Avatar 头像加载地址、禁用 Emoji 表情、后台禁用 Google Open Sans 字体

通过 WordPress Hook(钩子),当然这部分您也可以自定义,路径在主题目录:/functions.php

解决 Avatar 头像问题

function dmeng_get_https_avatar($avatar) {
	//~ 替换为 https 的域名
	$avatar = str_replace(array("www.gravatar.com", "0.gravatar.com", "1.gravatar.com", "2.gravatar.com"), "secure.gravatar.com", $avatar);
	//~ 替换为 https 协议
	$avatar = str_replace("http://", "https://", $avatar);
	return $avatar;
}
add_filter('get_avatar', 'dmeng_get_https_avatar');

这里是将访问 Avatar 的链接改为通过 https 来访问,如果不用 Avatar 功能,可取消 设置-讨论-头像-头像显示-显示头像 前面的对勾

也可使用 v2ex 或者 cdnjs 提供的 Avatar 图像加速服务

WordPress 禁用 Emoji 功能

function disable_emojis() {
remove_action( ‘wp_head’, ‘print_emoji_detection_script’, 7 );
remove_action( ‘admin_print_scripts’, ‘print_emoji_detection_script’ );
remove_action( ‘wp_print_styles’, ‘print_emoji_styles’ );
remove_action( ‘admin_print_styles’, ‘print_emoji_styles’ );
remove_filter( ‘the_content_feed’, ‘wp_staticize_emoji’ );
remove_filter( ‘comment_text_rss’, ‘wp_staticize_emoji’ );
remove_filter( ‘wp_mail’, ‘wp_staticize_emoji_for_email’ );
add_filter( ‘tiny_mce_plugins’, ‘disable_emojis_tinymce’ );
}
add_action( ‘init’, ‘disable_emojis’ );

function disable_emojis_tinymce( $plugins ) {
return array_diff( $plugins, array( ‘wpemoji’ ) );
}

wp 通过本地加载 google ajax

wp54 中使用 google ajax 服务的文件路径为wp-includes/script-loader.php

   738: 	$scripts->add( 'prototype', 'https://ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js', array(), '1.7.1' );
   739: 	$scripts->add( 'scriptaculous-root', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/scriptaculous.js', array( 'prototype' ), '1.9.0' );
   740: 	$scripts->add( 'scriptaculous-builder', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/builder.js', array( 'scriptaculous-root' ), '1.9.0' );
   741: 	$scripts->add( 'scriptaculous-dragdrop', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/dragdrop.js', array( 'scriptaculous-builder', 'scriptaculous-effects' ), '1.9.0' );
   742: 	$scripts->add( 'scriptaculous-effects', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/effects.js', array( 'scriptaculous-root' ), '1.9.0' );
   743: 	$scripts->add( 'scriptaculous-slider', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/slider.js', array( 'scriptaculous-effects' ), '1.9.0' );
   744: 	$scripts->add( 'scriptaculous-sound', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/sound.js', array( 'scriptaculous-root' ), '1.9.0' );
   745: 	$scripts->add( 'scriptaculous-controls', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/controls.js', array( 'scriptaculous-root' ), '1.9.0' );
  1663: 		$open_sans_font_url = "https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,300,400,600&subset=$subsets&display=fallback";
  1734: 	 * translators: Use this to specify the proper Google Font name and variants
  1738: 	$font_family = _x( 'Noto Serif:400,400i,700,700i', 'Google Font Name and Variants' );
  1740: 		$fonts_url = 'https://fonts.googleapis.com/css?family=' . urlencode( $font_family );

我已将下载好的文件上传到阿里 cdn 里,所以修改后的内容如下:

	// WordPress no longer uses or bundles Prototype or script.aculo.us. These are now pulled from an external source.
	$scripts->add( 'prototype', 'https://echoxucdn.oss-cn-shanghai.aliyuncs.com/googleajaxapis/prototype.js', array(), '1.7.1' );
	$scripts->add( 'scriptaculous-root', 'https://echoxucdn.oss-cn-shanghai.aliyuncs.com/googleajaxapis/scriptaculous.js', array( 'prototype' ), '1.9.0' );
	$scripts->add( 'scriptaculous-builder', 'https://echoxucdn.oss-cn-shanghai.aliyuncs.com/googleajaxapis/builder.js', array( 'scriptaculous-root' ), '1.9.0' );
	$scripts->add( 'scriptaculous-dragdrop', 'https://echoxucdn.oss-cn-shanghai.aliyuncs.com/googleajaxapis/dragdrop.js', array( 'scriptaculous-builder', 'scriptaculous-effects' ), '1.9.0' );
	$scripts->add( 'scriptaculous-effects', 'https://echoxucdn.oss-cn-shanghai.aliyuncs.com/googleajaxapis/effects.js', array( 'scriptaculous-root' ), '1.9.0' );
	$scripts->add( 'scriptaculous-slider', 'https://echoxucdn.oss-cn-shanghai.aliyuncs.com/googleajaxapis/slider.js', array( 'scriptaculous-effects' ), '1.9.0' );
	$scripts->add( 'scriptaculous-sound', 'https://echoxucdn.oss-cn-shanghai.aliyuncs.com/googleajaxapis/sound.js', array( 'scriptaculous-root' ), '1.9.0' );
	$scripts->add( 'scriptaculous-controls', 'https://echoxucdn.oss-cn-shanghai.aliyuncs.com/googleajaxapis/controls.js', array( 'scriptaculous-root' ), '1.9.0' );

当然我已经将这些文件下载并打包了,下面是下载地址:

wp54 google ajax 库文件下载地址

这样我们就可以让 wp 通过本地加载 google ajax 服务了.

提示

另外还可使用cdnjs提供的代理服务进行访问 google ajax. cdnjs 项目地址 CDNJS 加速 google ajax 库

移除 google fonts

/**WordPress 后台禁用 Google 字体*/
add_filter( 'gettext_with_context', 'wpjam_disable_google_fonts', 888, 4);
function wpjam_disable_google_fonts($translations, $text, $context, $domain ) {
	$google_fonts_contexts = array('Open Sans font: on or off','Lato font: on or off','Source Sans Pro font: on or off','Bitter font: on or off');
	if( $text == 'on' && in_array($context, $google_fonts_contexts ) ){
		$translations = 'off';
	}

	return $translations;
}

如果想继续使用 google fonts 也可通过 cdnjs 或者中科大提供的代理服务加载 google fonts

阻止站内文章互相 Pingback

/**
* 阻止站内文章互相Pingback
*/
function Bing_noself_ping($links) {
$home = get_option( ‘home’ );
foreach ( $links as $l => $link )
if ( 0 === strpos( $link, $home ) )
unset($links[$l]);
}
add_action(‘pre_ping’,’Bing_noself_ping’);

彻底关闭 WordPress 自动更新和后台更新检查

把如下代码 copy 到你主题的 functions.php,刷新后台.

add_filter('automatic_updater_disabled', '__return_true');	// 彻底关闭自动更新

remove_action('init', 'wp_schedule_update_checks');	// 关闭更新检查定时作业
wp_clear_scheduled_hook('wp_version_check');			// 移除已有的版本检查定时作业
wp_clear_scheduled_hook('wp_update_plugins');		// 移除已有的插件更新定时作业
wp_clear_scheduled_hook('wp_update_themes');			// 移除已有的主题更新定时作业
wp_clear_scheduled_hook('wp_maybe_auto_update');		// 移除已有的自动更新定时作业

remove_action( 'admin_init', '_maybe_update_core' );		// 移除后台内核更新检查

remove_action( 'load-plugins.php', 'wp_update_plugins' );	// 移除后台插件更新检查
remove_action( 'load-update.php', 'wp_update_plugins' );
remove_action( 'load-update-core.php', 'wp_update_plugins' );
remove_action( 'admin_init', '_maybe_update_plugins' );

remove_action( 'load-themes.php', 'wp_update_themes' );		// 移除后台主题更新检查
remove_action( 'load-update.php', 'wp_update_themes' );
remove_action( 'load-update-core.php', 'wp_update_themes' );
remove_action( 'admin_init', '_maybe_update_themes' );
/** 移除 WordPress 后台 logo */
function remove_logo($wp_toolbar) {
    $wp_toolbar->remove_node('wp-logo');
}
add_action('admin_bar_menu', 'remove_logo', 999);

七牛 CDN(可不配置)

因为使用了阿里云 cdn 进行加速,所以此项可不配置:

去七牛官网先注册七牛账号,会获得永久的 10G 空间。

然后新建一个对象存储空间,空间名随便取,空间权限选择“公开”。

然后绑定 CDN 加速域名,注意:此域名一定要是二级域名(此域名不用进行 A 标记解析),如果是网站域名,会导致网站打不开。

这里需要等七牛验证,验证通过会有一个 cname,然后将此域名在域名解析里解析即可。

注意:一定要用 cname 标记,然后主机记录填绑定的二级域名的前面部分,如我的是 image.echoxu.cn,那这里就填 image。

记录值填七牛给的 cname 值。

具体可参考七牛融合 CDN 官方文档

七牛融合 CDN

七牛配置及插件使用

七牛镜像

在七牛的对象存储里选择相应的空间名,然后选择镜像存储,这里填的域名是网站主域名。

解释下镜像存储,其实就相当于复制文件,及将主站的 jpg,css,js 等静态文件通过七牛云存储插件复制到新建的七牛对象存储空间中。

这里需要注意的是一定要选择七牛提供的 Robots.txt 文件,不然你的网站会被降权。

安装七牛云存储插件,需先安装 wpjam 插件并激活。

这两个插件是 wp 大神 我爱水煮鱼开发的,可在百度搜索 水煮鱼及可查看他的博客,里面会介绍很多 wp 的东西。

注意:wpjam 第一次激活时可能会提示“无效的主题内容”

可多点击几次激活,如果不行可删掉重新安装即可解决。

另需注意的是:启用后你还需扫描二维码关注 wpjam 的公众号,可通过扫码在公众号中查看 4 位验证码,但可能你会发现输入验证码后还是会停在扫码界面,根据水煮鱼大神的解释是服务器的原因,好像是 5 秒没反应,微信会拒绝。

我的解决办法是多扫几次,或者先取消关注公众号,再重新扫码,我就是这样通过的,再不行就只能换服务器了。

wpjam 的插件功能很多,具体可根据需要选择。

七牛镜像配置及七牛云存储插件使用可参考

七牛云存储

七牛镜像

wp 优化加速就写到这里,后续有补充再更新。

上次更新:
贡献者: iEchoxu