Nginx 隐藏服务器名称和版本号

注:默认读者自己会安装nginx,不会的就搜一下怎么安装吧。说明一点。在make的时候可以使用make -j num这里面的num是你的cpu核心数。这样会快一点~~~意为以num个进程同时编译

首先先说为什么要隐藏吧。这张图应该能说明问题了吧。对,就是为了解决安全隐患才这样做。就算升级到最新版本,该不公开还是要不公开的好吧~~ Nginx的版本号主要在两个地方会有: 第一个是HTTP header,有个Server:nginx/1.x.x类似会暴露Web服务器所用软件名称以及版本号,这个也是大多数Web服务器最容易暴露版本号的地方,如下:

怎么验证呢?输入curl -I 你的域名就可以了
HTTP/1.1 200 OK
Server: nginx/1.14.0
Date: Sun, 30 Sep 2018 05:11:14 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sun, 30 Sep 2018 03:44:42 GMT
Connection: keep-alive
ETag: "5bb046aa-264"
Accept-Ranges: bytes

接着再说说这个版本号吧。 如果安装好的童鞋可以直接在nginx.conf中配置一下就可以隐藏了。配置什么呢? 在你使用的nginx配置文件中的http节点下添加server_tokens off;就可以隐藏了。 第二个地方是Nginx出错页面,比如404页面没有找到等,这是如果用户没有指定页面的话,那么Nginx自己的页面会有版本戳记。

1、打开Nginx主配置文件:nginx.conf,取消注释或添加配置语句。

http { # …省略一些配置

server_tokens off;   #默认是注释掉的

# …省略一些配置}

2、编辑php-fpm配置文件,如fastcgi.conf或fcgi.conf(这个配置文件名也可以自定义的,根据具体文件名修改):

找到:

fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;

改为:

fastcgi_param SERVER_SOFTWARE nginx;

重启nginx完成 reload可以不断业务重载配置,也可以考虑直接重启。 这样就完全对外隐藏了nginx版本号了,就是出现404、501等页面也不会显示nginx版本   既然版本号可以隐藏,那可不可以隐藏或修改nginx服务器的名称呢?答案是可以,修改或隐藏服务器名称需要修改源码nginx.h,nginx.h在src/core/目录下 。具体操作如下: 把下面两个宏的值修改为自己设定的值,例如”NGX”。 都改为 “” 即隐藏名称。

vim src/core/nginx.h

#define NGINX_VER "nginx/" NGINX_VERSION 改为 #define NGINX_VER "hart-edu" NGINX_VERSION
#define NGINX_VAR "NGINX" 改为 #define NGINX_VAR "hart-edu"

同理改版本号修改#define NGINX_VERSION 后面的值

#define NGINX_VERSION      "1.14.0"
注意事项

1. 在配置文件nginx.conf中不要使用server_tokens off命令, 因为如果设置了该命令,服务器名称就固定了。 如果配置了server_tokens off,在解析文件时 clcf->server_tokens值为0。见ngx_http_core_module.c 的server_token命令处理函数ngx_conf_set_flag_slot

if (ngx_strcasecmp(value[1].data, (u_char *) "on") == 0) {
    *fp = 1;
} else if (ngx_strcasecmp(value[1].data, (u_char *) "off") == 0) {
    *fp = 0;
}

修改u_char ngx_http_server_string[]

vim src/http/ngx_http_header_filter_module.c

static char ngx_http_server_string[] = "Server: nginx" CRLF;
static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;

if (clcf->server_tokens) {
	p = (u_char *) ngx_http_server_full_string;
	len = sizeof(ngx_http_server_full_string) - 1;
} else {
	p = (u_char *) ngx_http_server_string;
	len = sizeof(ngx_http_server_string) - 1;
}

vim src/http/ngx_http_special_response.c

 static u_char ngx_http_error_tail[] =
 "<hr><center>nginx</center>" CRLF
 "</body>" CRLF
 "</html>" CRLF
 ;

每次修改都要记得保存哟。 之后重新编译安装nginx就可以了。 来测试一下看看。

[root@host ~]# curl -I 127.0.0.1
HTTP/1.1 200 OK
Server: hart-edu/0.0.1
Date: Sun, 30 Sep 2018 05:44:00 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sun, 30 Sep 2018 03:44:42 GMT
Connection: keep-alive
ETag: "5bb046aa-264"
Accept-Ranges: bytes

看已经将nginx信息隐藏了。

CentOS7下配置 iptables

iptables也叫netfilter,是Linux下自带的一款免费且优秀的基于包过滤的防火墙工具,他的功能十分强大,使用也非常灵活,可以对流入、流出、流经服务器的数据包进行精细的控制。但是iptables在CentOS7的版本上已经被阉割掉了,我们需要自行安装,以下是在CentOS7下安装iptables和使用方式。

一、安装iptables

命令

systemctl status iptables

返回

-bash: systemctl: command not found

输出结果表示没有iptables的相关服务,我们需要安装

停止firewal

systemctl stop firewalld.service

禁止firewall开机启动

systemctl disable firewalld.service

关闭SELINUX

vi /etc/selinux/config
#SELINUX=enforcing #注释掉
#SELINUXTYPE=targeted #注释掉
SELINUX=disabled #增加

保存退出

:wq!

使配置立即生效

setenforce 0

安装

yum install iptables-services

编辑防火墙配置文件

vi /etc/sysconfig/iptables
配置文件添加常用端口以后状态
# sample configuration for iptables service
# you can edit this manually or use system-config-firewall
# please do not ask us to add additional ports/services to this default configuration
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT

-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 20 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

保存退出

:wq!

二、命令

系统命令
systemctl start iptables #启动
systemctl status iptables #查看运行状态
systemctl restart iptables.service #重启
systemctl stop iptables.service #停止
systemctl enable iptables.service #设置开机启动
systemctl disable iptables.service #禁止开机启动

常用命令
iptables -h #查询帮助
iptables -L -n #列出(filter表)所有规则
iptables -L -n –line-number #列出(filter表)所有规则,带编号
iptables -L -n -t nat #列出(nat表)所有规则
iptables -F #清除(filter表)中所有规则
iptables -F -t nat #清除(nat表)中所有规则
service iptables save #保存配置(保存配置后必须重启iptables)
systemctl restart iptables.service #重启

三、语法

filter表解析
filter表是iptables默认使用的表,负责对流入、流出本机的数据包进行过滤,该表中定义了3个链,分别是:INPUT、OUTPUT、FORWARD
INPUT:过滤进入主机的数据包
OUTPUT:处理从本机出去的数据包
FORWARD:负责转发流经本机但不进入本机的数据包,起到转发作用
3.2、iptables常用语法
-A:追加到规则的最后一条
-D:删除记录
-I:添加到规则的第一条
-p:(proto)规定通信协议,常见的协议有:tcp、udp、icmp、all
-j:(jump)指定要跳转的目标,常见的目标有:ACCEPT(接收数据包)、DROP(丢弃数据包)、REJECT(重定向)三种,但是一般不适用重定向,会带来安全隐患

常见案例

4.1、IP过滤
4.1.1、禁止192.168.1.3 IP地址的所有类型数据接入
iptables -A INPUT ! -s 192.168.1.3 -j DROP
4.2、开放端口
4.2.1、开放端口
iptables -A INPUT -p tcp –dport 80 -j ACCEPT #开放80端口
4.2.2、开放端口范围
iptables -I INPUT -p tcp –dport 22:80 -j ACCEPT #开发22-80范围的端口
4.2.3、不允许80端口流出
iptables -I OUTPUT -p tcp –dport 80 -j DROP

centos7 安装bbr教程

Google 开源了其 TCP BBR 拥塞控制算法,并提交到了 Linux 内核,从 4.9 开始,Linux 内核已经用上了该算法。根据以往的传统,Google 总是先在自家的生产环境上线运用后,才会将代码开源,此次也不例外。
根据实地测试,在部署了最新版内核并开启了 TCP BBR 的机器上,网速甚至可以提升好几个数量级。

建议使用BBR透明并且使用方便,BBR作为现在TCP比较好的拥塞控制协议,通过对于带宽和网络延迟的交替估计更加准确控制发送窗口的大小。Centos7开启方法:

1. yum系统更新

yum update -y

​2.查看系统版本

cat /etc/redhat-release

输出如下,则表示已升级到7.5(当前最新)

CentOS Linux release 7.5.1804 (Core)

3.安装elrepo并升级内核

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm

yum --enablerepo=elrepo-kernel install kernel-ml -y

正常情况下将输出如下,

Transaction Summary
================================================================================
Install  1 Package

Total download size: 39 M
Installed size: 169 M
Downloading packages:
kernel-ml-4.9.0-1.el7.elrepo.x86_64.rpm                    |  39 MB   00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Warning: RPMDB altered outside of yum.
  Installing : kernel-ml-4.9.0-1.el7.elrepo.x86_64                          1/1
  Verifying  : kernel-ml-4.9.0-1.el7.elrepo.x86_64                          1/1
  
Installed:
  kernel-ml.x86_64 0:4.9.0-1.el7.elrepo
  
Complete!

3.更新grub文件并重启(reboot后,ssh会断开,稍等一会儿重新连接)

egrep ^menuentry /etc/grub2.cfg | cut -f 2 -d \'
grub2-set-default 0
reboot

4.开机后查看内核是否已更换为4.9

uname -r

输出如下内容则表示内核4.9已经启动了

4.18.9-1.el7.elrepo.x86_64

5.开启bbr

vi /etc/sysctl.conf

添加如下内容

net.core.default_qdisc = fq 
net.ipv4.tcp_congestion_control = bbr

加载系统参数(正常情况下会输出我们之前加入的内容)

sysctl -p

4.确定bbr已经开启

输入

sysctl net.ipv4.tcp_available_congestion_control

返回

net.ipv4.tcp_available_congestion_control = reno cubic bbr

则安装成功

输入

lsmod | grep bbr

返回

tcp_bbr                20480  16

启动成功

使用BBR为你的CentOS/Debian/Ubuntu系统加速

自Google于2016年9月宣布将BBR开源起,世界各国的极客们就开始研究了,对于常年受制于特殊网络环境下的我国民众,长期都在寻找各种提速的方法。之前流行的锐速(后开始收费)以及FinalSpeed等都曾备受大家的“爱戴”。对于bbr而言,通俗来讲就是对Linux内核TCP协议的优化从而达到提速的目的,但是注意的是,1)bbr不能改变地理位置的限制,也就是说他不会改变网络的线路,该绕还是绕;2)安装和开启bbr往往要更新内核,因此对于VPS而言,推荐选择KVM构架。本文将简述bbr在CentOS 7下的安装和启用的方法,亲测有效,整个流程也十分简单。对于Debian或者Ubuntu的用户我会在后面的教程中加以补充。

一键脚安装BBR

使用root用户登录,运行以下命令:

wget --no-check-certificate https://github.com/teddysun/across/raw/master/bbr.sh
chmod +x bbr.sh
./bbr.sh

# 备用地址

wget --no-check-certificate -qO 'BBR.sh' 'https://www.moerats.com/usr/down/BBR.sh' && chmod a+x BBR.sh && bash BBR.sh -f

魔改BBR

一键地址默认是选择官方提供的最新版本的内核,如想要指定内核则运行指定内核版本一键包即可!

(1)一键地址

wget --no-check-certificate -qO 'BBR_POWERED.sh' 'https://moeclub.org/attachment/LinuxShell/BBR_POWERED.sh' && chmod a+x BBR_POWERED.sh && bash BBR_POWERED.sh
# 备用地址
wget --no-check-certificate -qO 'BBR_POWERED.sh' 'https://www.moerats.com/usr/down/BBR_POWERED.sh' && chmod a+x BBR_POWERED.sh && bash BBR_POWERED.sh

(2)指定内核版本(以v4.11.9内核版本为例)

wget --no-check-certificate -qO 'BBR_POWERED.sh' 'https://moeclub.org/attachment/LinuxShell/BBR_POWERED.sh' && chmod a+x BBR_POWERED.sh && bash BBR_POWERED.sh -f v4.11.9
# 备用地址
wget --no-check-certificate -qO 'BBR_POWERED.sh' 'https://www.moerats.com/usr/down/BBR_POWERED.sh' && chmod a+x BBR_POWERED.sh && bash BBR_POWERED.sh -f v4.11.9

安装完成后,脚本会提示需要重启 VPS,输入 y 并回车后重启。
重启完成后,进入 VPS,验证一下是否成功安装最新内核并开启 TCP BBR,输入以下命令:

uname -r
查看内核版本,含有 4.12 就表示 OK 了

sysctl net.ipv4.tcp_available_congestion_control
返回值一般为:
net.ipv4.tcp_available_congestion_control = bbr cubic reno

sysctl net.ipv4.tcp_congestion_control
返回值一般为:
net.ipv4.tcp_congestion_control = bbr

sysctl net.core.default_qdisc
返回值一般为:
net.core.default_qdisc = fq

lsmod | grep bbr
返回值有 tcp_bbr 模块即说明bbr已启动。

SSR一键搭建MU版本

SHADOWSOCKSR mu版本 一键脚本

本脚本与另一个SSR脚本 『原创』CentOS/Debian/Ubuntu ShadowsocksR 单/多端口 一键管理脚本的区别是什么?

ssrmu.sh脚本是单服务器多用户脚本,使用的是 SSR服务端的MudbJSON模式,可以给每个用户(端口)设置不同的加密方式/协议/混淆/限制速度/设备数限制/可用总流量等功能。即实现单服务器多用户流量管理等功能。

而 ssr.sh则是单服务器单用户脚本,使用的是 SSR服务端的单用户配置方式,即使实现了多端口,但是还算不算多用户,不支持每个用户(端口)不同的加密方式/协议/混淆等,并且无法管理流量使用。

脚本特点:

目前网上的各个ShadowsocksR脚本基本都是只有 安装/启动/重启 等基础功能,对于小白来说还是不够简单方便。既然是一键脚本,那么就要尽可能地简单,小白更容易接受使用!

支持 限制 用户速度

支持 限制 端口设备数

支持 显示 当前连接IP

支持 显示 SS/SSR连接+二维码

支持 切换管理 单/多端口

支持 一键安装 锐速

支持 一键安装 BBR

支持 一键封禁 垃圾邮件(SMAP)/BT/PT

 

如何选择这两个脚本?

根据你的需求选择,比如你仅仅是 一个或两个人使用,并且不需要流量管理功能,那么选择 ssr.sh好了。而如果很多人使用,并且都需要限制流量来管理,那你适合使用 ssrmu.sh,所以自己看着选,多试试(两个脚本不能共存)

 

shadowcosksr mu 一键安装

wget -N –no-check-certificate https://www.wuwweb.com/ssrmu.sh && chmod +x ssrmu.sh && bash ssrmu.sh
备用下载
wget -N –no-check-certificate https://raw.githubusercontent.com/ToyoDAdoubi/doubi/master/ssrmu.sh && chmod +x ssrmu.sh && bash ssrmu.sh

继续阅读“SSR一键搭建MU版本”

Linux Centos 7 systemctl(systemd)新增加service服务,并且开机启动

centos 7中采用了systemd控制系统服务,更加简单,以前启动服务需要 service xxxx start|stop等。现在需要的是systemctl start|stop xxx。比如我配置的启动tomcat,systemctl start tomcat。十分方便。以前是在,现在直接在/usr/lib/systemd/system里面新建一个tomcat.service,内容如下:

[Unit]  
Description=tomcatapi  
After=network.target  
   
[Service]  
Type=forking  
ExecStart=/usr/local/soft/tomcat/tomcat8/bin/startup.sh  
ExecReload=  
ExecStop=/usr/local/soft/tomcat/tomcat8/bin/shutdown.sh  
PrivateTmp=true  
   
[Install]  
WantedBy=multi-user.target  

然后给这个tomcat.service 文件chomod +x权限即可!最后在重启下systemctl,命令如下:systemctl daemon-reload

最后就可以通过systemctl start tomcat启动啦!

上面的tomcat.service需要按需更改。里面的路径不一样。

以下是转载的:

设置分为三个部份

  • [Unit]: unit 本身的说明,以及与其他相依 daemon 的设置,包括在什么服务之后才启动此 unit 之类的设置值;
  • [Service], [Socket], [Timer], [Mount], [Path]..:不同的 unit type 就得要使用相对应的设置项目。我们拿的是 sshd.service 来当范本,所以这边就使用 [Service] 来设置。 这个项目内主要在规范服务启动的脚本、环境配置文件文件名、重新启动的方式等等。
  • [Install]:这个项目就是将此 unit 安装到哪个 target 里面去的意思!

至于配置文件内有些设置规则还是得要说明一下:

  • 设置项目通常是可以重复的,例如我可以重复设置两个 After 在配置文件中,不过,后面的设置会取代前面的喔!因此,如果你想要将设置值归零, 可以使用类似“ After= ”的设置,亦即该项目的等号后面什么都没有,就将该设置归零了 (reset)。
  • 如果设置参数需要有“是/否”的项目 (布林值, boolean),你可以使用 1, yes, true, on 代表启动,用 0, no, false, off 代表关闭!随你喜好选择啰!
  • 空白行、开头为 # 或 ; 的那一行,都代表注解!

每个部份里面还有很多的设置细项,我们使用一个简单的表格来说明每个项目好了!

[Unit] 部份
设置参数 参数意义说明
Description 就是当我们使用 systemctl list-units 时,会输出给管理员看的简易说明!当然,使用 systemctl status 输出的此服务的说明,也是这个项目!
Documentation 这个项目在提供管理员能够进行进一步的文件查询的功能!提供的文件可以是如下的数据:Documentation=http://www....Documentation=man:sshd(8)Documentation=file:/etc/ssh/sshd_config
After 说明此 unit 是在哪个 daemon 启动之后才启动的意思!基本上仅是说明服务启动的顺序而已,并没有强制要求里头的服务一定要启动后此 unit 才能启动。 以 sshd.service 的内容为例,该文件提到 After 后面有 network.target 以及 sshd-keygen.service,但是若这两个 unit 没有启动而强制启动 sshd.service 的话, 那么 sshd.service 应该还是能够启动的!这与 Requires 的设置是有差异的喔!
Before 与 After 的意义相反,是在什么服务启动前最好启动这个服务的意思。不过这仅是规范服务启动的顺序,并非强制要求的意思。
Requires 明确的定义此 unit 需要在哪个 daemon 启动后才能够启动!就是设置相依服务啦!如果在此项设置的前导服务没有启动,那么此 unit 就不会被启动!
Wants 与 Requires 刚好相反,规范的是这个 unit 之后最好还要启动什么服务比较好的意思!不过,并没有明确的规范就是了!主要的目的是希望创建让使用者比较好操作的环境。 因此,这个 Wants 后面接的服务如果没有启动,其实不会影响到这个 unit 本身!
Conflicts 代表冲突的服务!亦即这个项目后面接的服务如果有启动,那么我们这个 unit 本身就不能启动!我们 unit 有启动,则此项目后的服务就不能启动! 反正就是冲突性的检查啦!

接下来了解一下在 [Service] 当中有哪些项目可以使用!

[Service] 部份
设置参数 参数意义说明
Type 说明这个 daemon 启动的方式,会影响到 ExecStart 喔!一般来说,有下面几种类型 simple:默认值,这个 daemon 主要由 ExecStart 接的指令串来启动,启动后常驻于内存中。forking:由 ExecStart 启动的程序通过 spawns 延伸出其他子程序来作为此 daemon 的主要服务。原生的父程序在启动结束后就会终止运行。 传统的 unit 服务大多属于这种项目,例如 httpd 这个 WWW 服务,当 httpd 的程序因为运行过久因此即将终结了,则 systemd 会再重新生出另一个子程序持续运行后, 再将父程序删除。据说这样的性能比较好!!oneshot:与 simple 类似,不过这个程序在工作完毕后就结束了,不会常驻在内存中。dbus:与 simple 类似,但这个 daemon 必须要在取得一个 D-Bus 的名称后,才会继续运行!因此设置这个项目时,通常也要设置 BusName= 才行!idle:与 simple 类似,意思是,要执行这个 daemon 必须要所有的工作都顺利执行完毕后才会执行。这类的 daemon 通常是开机到最后才执行即可的服务!比较重要的项目大概是 simple, forking 与 oneshot 了!毕竟很多服务需要子程序 (forking),而有更多的动作只需要在开机的时候执行一次(oneshot),例如文件系统的检查与挂载啊等等的。
EnvironmentFile 可以指定启动脚本的环境配置文件!例如 sshd.service 的配置文件写入到 /etc/sysconfig/sshd 当中!你也可以使用 Environment= 后面接多个不同的 Shell 变量来给予设置!
ExecStart 就是实际执行此 daemon 的指令或脚本程序。你也可以使用 ExecStartPre (之前) 以及 ExecStartPost (之后) 两个设置项目来在实际启动服务前,进行额外的指令行为。 但是你得要特别注意的是,指令串仅接受“指令 参数 参数…”的格式,不能接受 <, >, >>, |, & 等特殊字符,很多的 bash 语法也不支持喔! 所以,要使用这些特殊的字符时,最好直接写入到指令脚本里面去!不过,上述的语法也不是完全不能用,亦即,若要支持比较完整的 bash 语法,那你得要使用 Type=oneshot 才行喔! 其他的 Type 才不能支持这些字符。
ExecStop 与 systemctl stop 的执行有关,关闭此服务时所进行的指令。
ExecReload 与 systemctl reload 有关的指令行为
Restart 当设置 Restart=1 时,则当此 daemon 服务终止后,会再次的启动此服务。举例来说,如果你在 tty2 使用文字界面登陆,操作完毕后登出,基本上,这个时候 tty2 就已经结束服务了。 但是你会看到屏幕又立刻产生一个新的 tty2 的登陆画面等待你的登陆!那就是 Restart 的功能!除非使用 systemctl 强制将此服务关闭,否则这个服务会源源不绝的一直重复产生!
RemainAfterExit 当设置为 RemainAfterExit=1 时,则当这个 daemon 所属的所有程序都终止之后,此服务会再尝试启动。这对于 Type=oneshot 的服务很有帮助!
TimeoutSec 若这个服务在启动或者是关闭时,因为某些缘故导致无法顺利“正常启动或正常结束”的情况下,则我们要等多久才进入“强制结束”的状态!
KillMode 可以是 process, control-group, none 的其中一种,如果是 process 则 daemon 终止时,只会终止主要的程序 (ExecStart 接的后面那串指令),如果是 control-group 时, 则由此 daemon 所产生的其他 control-group 的程序,也都会被关闭。如果是 none 的话,则没有程序会被关闭喔!
RestartSec 与 Restart 有点相关性,如果这个服务被关闭,然后需要重新启动时,大概要 sleep 多少时间再重新启动的意思。默认是 100ms (毫秒)。

最后,再来看看那么 Install 内还有哪些项目可用?

[Install] 部份
设置参数 参数意义说明
WantedBy 这个设置后面接的大部分是 *.target unit !意思是,这个 unit 本身是附挂在哪一个 target unit 下面的!一般来说,大多的服务性质的 unit 都是附挂在 multi-user.target 下面!
Also 当目前这个 unit 本身被 enable 时,Also 后面接的 unit 也请 enable 的意思!也就是具有相依性的服务可以写在这里呢!
Alias 进行一个链接的别名的意思!当 systemctl enable 相关的服务时,则此服务会进行链接文件的创建!以 multi-user.target 为例,这个家伙是用来作为默认操作环境 default.target 的规划, 因此当你设置用成 default.target 时,这个 /etc/systemd/system/default.target 就会链接到 /usr/lib/systemd/system/multi-user.target 啰!

两则预防crontab重复执行任务策略

首先说说cron,它是一个linux下的定时执行工具。根用户以外的用户可以使用 crontab 工具来配置 cron 任务。所有用户定义的 crontab 都被保存在/var/spool/cron 目录中,并使用创建它们的用户身份来执行。要以某用户身份创建一个 crontab 项目,登录为该用户,然后键入 crontab -e 命令来编辑该用户的 crontab。该文件使用的格式和 /etc/crontab 相同。当对 crontab 所做的改变被保存后,该 crontab 文件就会根据该用户名被保存,并写入文件 /var/spool/cron/username 中。cron 守护进程每分钟都检查 /etc/crontab 文件、etc/cron.d/ 目录、以及 /var/spool/cron 目录中的改变。如果发现了改变,它们就会被载入内存。这样,当某个 crontab 文件改变后就不必重新启动守护进程了。

centos7.5安装crontab

yum intall -y cronie

  1. 基本格式 :
  2. * * * * * command
  3. 分 时 日 月 周 命令
  4. 第1列表示分钟1~59 每分钟用*或者 */1表示
  5. 第2列表示小时1~23(0表示0点)
  6. 第3列表示日期1~31
  7. 第4列表示月份1~12
  8. 第5列标识号星期0~6(0表示星期天)
  9. 第6列要运行的命令

crontab 执行 php 脚本

linux 下的 crontab 定时任务服务,可以用来定时运行脚本。工作中经常会用到这样的服务,使用起来比较简单。

在目前的 CentOS 7(或 RHEL 7)系统中,依然可以使用 service 指令.例如,

[root@localhost ~]# service network restart
Restarting network (via systemctl): [OK ]
[root@localhost ~]# service httpd restart
Redirecting to /bin/systemctl restart httpd.service
[root@localhost ~]# service sshd restart
Redirecting to /bin/systemctl restart sshd.service

但是系统会自动重定向该指令到新的指令 /bin/systemctl 来执行,并给出提示.

启动服务:

systemctl start httpd

停止服务:

systemctl stop httpd

重启服务(先停止,后启动):

systemctl restart httpd

重新加载(使用新的配置文件):

systemctl reload httpd

显示服务状态:

systemctl status httpd

与此同时,之前用于设定系统启动时自动运行某服务的指令 chkconfig 也改了,还是用 systemctl.

chkconfig service on

改成了,

systemctl enablehttpd

扫描改动过的服务

systemctl daemon-reload
chkconfig service off

改成了,

systemctl disable httpd

检查服务状态的

chkconfig service

改成了,

systemctl is-enabled httpd

列举出所有服务的指令,

chkconfig –list

改成了,

systemctl list-unit-files --type=service

以前能指定服务 runlevel 的 –levels 也没有了.慢慢适应吧.

参 数:
-e 编辑该用户的计时器设置。
-l 列出该用户的计时器设置。
-r 删除该用户的计时器设置。
-u<用户名称> 指定要设定计时器的用户名称。

crontab 格式:

基本格式 :

分钟 小时 日 月 星期 命令

* * * * * *

第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列 表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令

记住几个特殊符号的含义:
“*”代表取值范围内的数字,
“/”代表”每”,
“-”代表从某个数字到某个数字,
“,”分开几个离散的数字

预防crontab重复执行任

最近在工作中经常会用到定时任务,发现当我们的脚步的执行时间(假设:130s)大于定时任务的设定时间(假设:1分钟)时,定时任务会重复开始执行,即上次的任务还没有执行完,下次的任务的又开始执行。往往执行的脚本里的资源是不允许同时两个脚本同时共享资源,即保证操作的原子性。这样会造成执行出错,下面我们来验证一下。

以下是一个测试的 php 脚本,该脚本执行一次需要 130s

<?php
$time = time();$id = uniqid(); //一次执行的唯一标示 
file_put_contents('/home/phachon/cron/test.log', "id: ".$id." 时间:".date('Y-m-d H:i:s', $time)."-开始\n", FILE_APPEND);
while(time() - $time < 130) {
 } 
file_put_contents('/home/phachon/cron/test.log', "id: ".$id." 时间:".date('Y-m-d H:i:s', time())."-结束\n", FILE_APPEND);

然后添加定时任务,每分钟(60s)执行一次

*/1 * * * * php /home/phachon/cron/test.php

过一段时间后,查看日志:

id: 57bbcd4d10262 时间:2016-08-23 12:13:01-开始
id: 57bbcd890e7f7 时间:2016-08-23 12:14:01-开始
id: 57bbcdc510685 时间:2016-08-23 12:15:01-开始
id: 57bbcd4d10262 时间:2016-08-23 12:15:11-结束
id: 57bbce010a78d 时间:2016-08-23 12:16:01-开始
id: 57bbcd890e7f7 时间:2016-08-23 12:16:11-结束
id: 57bbce3d0f68e 时间:2016-08-23 12:17:01-开始
id: 57bbcdc510685 时间:2016-08-23 12:17:11-结束
id: 57bbce790d90f 时间:2016-08-23 12:18:01-开始
id: 57bbce010a78d 时间:2016-08-23 12:18:11-结束
id: 57bbceb50eef8 时间:2016-08-23 12:19:01-开始
id: 57bbce3d0f68e 时间:2016-08-23 12:19:11-结束
id: 57bbce790d90f 时间:2016-08-23 12:20:11-结束
id: 57bbceb50eef8 时间:2016-08-23 12:21:11-结束

分析日志我们会发现 id = 57bbcd4d10262 的任务在 12:13:01 开始,但是还没有结束的时候,id=57bbcd890e7f7 和 id=57bbcdc510685 的任务就已经开始了,这样明显存在问题。我们想要的是每次单独执行完后,下一个执行开始:

id: 57bbcd4d10262 时间:2016-08-23 12:13:01-开始
id: 57bbcd4d10262 时间:2016-08-23 12:15:11-结束
id: 57bbcd890e7f7 时间:2016-08-23 12:14:01-开始
id: 57bbcd890e7f7 时间:2016-08-23 12:16:11-结束

解决办法

1,利用临时文件

思路很简单,在执行文件的开头先判断是否有一个 test.lock 的文件,如果有 test.lock 文件,则 exit(),如果没有的话,创建 test.lock 文件,然后执行脚本文件,执行完毕删除 test.lock;
实现后代码:

 <?php
   $time = time();
   $id = uniqid();
   $lock = '/home/phachon/cron/lock/test.lock';
   if(file_exists($lock)) {
       exit('no');
   }
   touch($lock);

   file_put_contents('/home/phachon/cron/test2.log', "id: ".$id." 时间:".date('Y-m-d H:i:s', $time)."-开始\n", FILE_APPEND);
   while(time() - $time < 130) {

   }

   file_put_contents('/home/phachon/cron/test2.log', "id: ".$id." 时间:".date('Y-m-d H:i:s', time())."-结束\n", FILE_APPEND);
   unlink($lock);

查看日志如下:

 id: 57bbdd3d6b5e8 时间:2016-08-23 13:21:01-开始
 id: 57bbdd3d6b5e8 时间:2016-08-23 13:23:11-结束
 id: 57bbddf10ecb9 时间:2016-08-23 13:24:01-开始
 id: 57bbddf10ecb9 时间:2016-08-23 13:26:11-结束

2,利用脚本加锁

思路和第一种方式类似,只是不是用文件判断的方式,而是给文件加锁的方式

实现代码:

<?php
$fp = fopen("/tmp/lock.txt", "w+");
// 进行排它型锁定
if (flock($fp, LOCK_EX | LOCK_NB)) {
   //执行任务
   run(); 
   // 释放锁定
   flock($fp, LOCK_UN); 
} else {
   echo "文件被锁定";
}
fclose($fp);
?>

第一种和第二种方法本质思路一样,确实也解决了问题,但是这样需要加代码在我们的脚本里,而且,这样其实 crontab 服务还是多了很多不必要的执行,浪费资源。
我们需要找到更加好的方法,在执行代码前就已经判断是否可以执行脚本。

对子任务加锁(如果有)

mysql的innodb update操作是行锁的,可以利用这点对子任务加锁,一条数据代表一个子任务
这样可以更西粒度的控制一个子任务同一时刻只有一个进程在执行,同时还可以开启多个进程。

 

function run($procid=0)//人为标识的进程id
{
$procNum = 10;//假设开10个进程


$data = select(..) from .. where id%$procNum=$procid;
foreach($data as $row){
exec($row);
}



}


function exec($val)
{
//lock
if(model()->lock($val['id'])) //执行一条update table set status='lock' where id=12312 and status='unlock';
return;
...run..
model()->succ($val['id']);

}

crontab脚本

​0* * * * /proc id=0

1* * * * /proc id=1

2* * * * /proc id=2

9* * * * /proc id=9

3,使用linux flock 文件锁实现任务锁定,解决冲突

利用 flock(FreeBSD lockf,CentOS下为 flock),在脚本执行前先检测能否获取某个文件锁,以防止脚本运行冲突。

格式:

 flock [-sxun][-w #] fd#
 flock [-sxon][-w #] file [-c] command

选项:

 -s, --shared:    获得一个共享锁 #共享锁,在定向为某文件的FD上设置共享锁而未释放锁的时间内,其他进程试图在定向为此文件的FD上设置独占锁的请求失败,而其他进程试图在定向为此文件的FD上设置共享锁的请求会成功
 -x, --exclusive: 获得一个独占锁 #独占或排他锁,在定向为某文件的FD上设置独占锁而未释放锁的时间内,其他进程试图在定向为此文件的FD上设置共享锁或独占锁都会失败。只要未设置-s参数,此参数默认被设置
 -u, --unlock:    移除一个锁,脚本执行完会自动丢弃锁 #手动解锁,一般情况不必须,当FD关闭时,系统会自动解锁,此参数用于脚本命令一部分需要异步执行,一部分可以同步执行的情况
 -n, --nonblock:  如果没有立即获得锁,直接失败而不是等待 #为非阻塞模式,当试图设置锁失败,采用非阻塞模式,直接返回1,
 -w, --timeout:   如果没有立即获得锁,等待指定时间 #设置阻塞超时,当超过设置的秒数,就跳出阻塞,返回1
 -o, --close:     在运行命令前关闭文件的描述符号。用于如果命令产生子进程时会不受锁的管控 
 -c, --command:   在shell中运行一个单独的命令 
 -h, --help       显示帮助 
 -V, --version:   显示版本

锁类型:

文件锁使用独占锁,非阻塞模式 如果锁定则失败不等待。参数为-xn

*/1 * * * *  flock -xn /tmp/test.lock -c 'php /home/phachon/cron/test.php' >> /home/phachon/cron/cron.log'

阻塞模式

*/1 * * * *  flock -x /tmp/test.lock -c 'php /home/phachon/cron/test.php' >> /home/phachon/cron/cron.log'

日志如下:

id: 57bbf255e4b2b 时间:2016-08-23 14:51:01-开始
id: 57bbf255e4b2b 时间:2016-08-23 14:53:11-结束
id: 57bbf3090eca0 时间:2016-08-23 14:54:01-开始
id: 57bbf3090eca0 时间:2016-08-23 14:56:11-结束

CentOS7使用yum安装配置MySQL8

卸载MariaDB

列出所有被安装的rpm package

# rpm -qa | grep mariadb
mariadb-libs-5.5.50-1.el7_2.x86_64
mariadb-5.5.50-1.el7_2.x86_64
mariadb-server-5.5.50-1.el7_2.x86_64

强制卸载

rpm -e mariadb-libs-5.5.50-1.el7_2.x86_64

此时报错:

error: Failed dependencies:
    libmysqlclient.so.18()(64bit) is needed by (installed) postfix-2:2.10.1-6.el7.x86_64
    libmysqlclient.so.18()(64bit) is needed by (installed) perl-DBD-MySQL-4.023-5.el7.x86_64
    libmysqlclient.so.18()(64bit) is needed by (installed) php-mysql-5.4.16-36.3.el7_2.x86_64
    libmysqlclient.so.18(libmysqlclient_18)(64bit) is needed by (installed) postfix-2:2.10.1-6.el7.x86_64
    libmysqlclient.so.18(libmysqlclient_18)(64bit) is needed by (installed) perl-DBD-MySQL-4.023-5.el7.x86_64
    libmysqlclient.so.18(libmysqlclient_18)(64bit) is needed by (installed) php-mysql-5.4.16-36.3.el7_2.x86_64
    mariadb-libs(x86-64) = 1:5.5.50-1.el7_2 is needed by (installed) mariadb-1:5.5.50-1.el7_2.x86_64
    mariadb-libs(x86-64) = 1:5.5.50-1.el7_2 is needed by (installed) mariadb-server-1:5.5.50-1.el7_2.x86_64

强制卸载,因为没有–nodeps

# rpm -e --nodeps mariadb-libs-5.5.50-1.el7_2.x86_64

# rpm -e --nodeps mariadb-5.5.50-1.el7_2.x86_64

# rpm -e --nodeps mariadb-server-5.5.50-1.el7_2.x86_64 

安装MySQL

下载MySQL源(后缀是noarch.rpm)

[root@centos ~]# wget https://repo.mysql.com//mysql80-community-release-el7-1.noarch.rpm

安装mysql源

[root@centos ~]# yum localinstall mysql80-community-release-el7-1.noarch.rpm

检查mysql源是否安装成功

[root@centos ~]# yum repolist enabled | grep "mysql.*-community.*"

出现如下所示表示安装成功:

mysql-connectors-community/x86_64 MySQL Connectors Community                  65
mysql-tools-community/x86_64      MySQL Tools Community                       69
mysql80-community/x86_64          MySQL 8.0 Community Server                  33

安装MySQL

[root@centos ~]# yum install mysql-community-server

出现Error downloading packages:错误,重复执行上述命令。

启动MySQL服务

[root@centos ~]# systemctl start mysqld

查看MySQL的启动状态

[root@centos ~]# systemctl status mysqld

找出root默认密码

mysql安装完成之后,在/var/log/mysqld.log文件中给root生成了一个默认密码。通过下面的方式找到root默认密码,然后登录mysql进行修改。

[root@centos ~]# grep 'temporary password' /var/log/mysqld.log
2018-05-13T02:02:14.879263Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: &/hQlEZXc1gT

使用数据库root用户登录

[root@centos ~]# mysql -u root -p
Enter password: &/hQlEZXc1gT

修改默认密码

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'Mysql&123456789';
mysql> flush privileges;

修改默认密码和加密方式

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '%KMzSp43m5XKC@eP';
flush privileges;

注意:mysql5.7以上默认安装了密码安全检查插件(validate_password),默认密码检查策略要求密码必须包含:大小写字母、数字和特殊符号,并且长度不能少于8位。否则会提示ERROR 1819 (HY000)错误,如下图所示:

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123456789';
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

远程连接授权

mysql> use mysql;
mysql> select user,host from user;
mysql> update user set host = '%' where user = 'root';

重启MySQL

[root@centos ~]# systemctl restart mysqld;

Mysql 安装完客户端连接报错:“Authentication plugin ‘caching_sha2_password’ cannot be loaded: ”

意思是客户端不支持caching_sha2_password的加密方式。

这样是不是就可以了呢? 其实并不会,还有一个坑

执行命令

use mysql;
select user,plugin from user ;

可以看到root用户的加密方式为caching_sha2_password

这样的话有两种办法可以解决问题:

一、升级客户端支持caching_sha2_password方式,没有采用。

我使用第二种方法:

二、修改密码加密方式,改成mysql_native_password

# 注意这里’%’是因为我们刚刚把user表中的localhost换成了%

ALTERUSER'root'@'%'IDENTIFIED BY'password'PASSWORD EXPIRE NEVER;

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

FLUSH PRIVILEGES;

 

# 查看一下现在的user表

select host, user, authentication_string, plugin from user;

可以看到plugin那我们已经换过来了

现在就可以正常的使用小海豚或者navicat Premium登录了

Nginx开启Gzip详解

1. Nginx开启Gzip

Nginx实现资源压缩的原理是通过ngx_http_gzip_module模块拦截请求,并对需要做gzip的类型做gzip,ngx_http_gzip_module是Nginx默认集成的,不需要重新编译,直接开启即可。

1.1 配置说明

Nginx开启Gzip的配置如下:

# $gzip_ratio计算请求的压缩率,$body_bytes_sent请求体大小
    log_format  main  '$remote_addr - $remote_user [$time_local] "$host" - "$request" '
                    '$gzip_ratio - $body_bytes_sent - $request_time';


    access_log  logs/access.log  main;

    # 开启gzip
    gzip off;

    # 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
    gzip_min_length 1k;

    # gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
    gzip_comp_level 1;

    # 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;

    # 是否在http header中添加Vary: Accept-Encoding,建议开启
    gzip_vary on;

    # 禁用IE 6 gzip
    gzip_disable "MSIE [1-6]\.";

    # 设置压缩所需要的缓冲区大小     
    gzip_buffers 32 4k;

    # 设置gzip压缩针对的HTTP协议版本
    gzip_http_version 1.0;

下面将逐条介绍下gzip的指令和参数配置。

1.2 参数详解

gzip on

这个没的说,打开或关闭gzip

SSyntax: gzip on | off;
Default:    
gzip off;
Context:    http, server, location, if in location

gzip_buffers

设置用于处理请求压缩的缓冲区数量和大小。比如32 4K表示按照内存页(one memory page)大小以4K为单位(即一个系统中内存页为4K),申请32倍的内存空间。建议此项不设置,使用默认值。

Syntax: gzip_buffers number size;
Default:    
gzip_buffers 32 4k|16 8k;
Context:    http, server, location

gzip_comp_level

设置gzip压缩级别,级别越底压缩速度越快文件压缩比越小,反之速度越慢文件压缩比越大

Syntax: gzip_comp_level level;
Default:    
gzip_comp_level 1;
Context:    http, server, location

我们以一个大小为92.6K的脚本文件为例,如下所示。其中最后三个数值分别表示压缩比、包大小、平均处理时间(使用ab压测,100用户并发下, ./ab -n 10000 -c 100 -H 'Accept-Encoding: gzip' http://10.27.180.75/jquery.js)以及CPU消耗。

从这我们可以得出结论:

  1. 随着压缩级别的升高,压缩比有所提高,但到了级别6后,很难再提高;
  2. 随着压缩级别的升高,处理时间明显变慢;
  3. gzip很消耗cpu的性能,高并发情况下cpu达到100%

因此,建议:
一方面,不是压缩级别越高越好,其实gzip_comp_level 1的压缩能力已经够用了,后面级别越高,压缩的比例其实增长不大,反而很吃处理性能。
另一方面,压缩一定要和静态资源缓存相结合,缓存压缩后的版本,否则每次都压缩高负载下服务器肯定吃不住。

http://10.27.180.75/jquery.js 
gzip_comp_level 0: 0,94840, 63 [ms], 29%
gzip_comp_level 1: 2.43,39005, 248 [ms], 100%
gzip_comp_level 2: 2.51,37743, 273 [ms], 100%
gzip_comp_level 3; 2.57,36849, 327 [ms], 100%
gzip_comp_level 4; 2.73,34807, 370 [ms], 100%
gzip_comp_level 5; 2.80,33898, 491 [ms], 100%
gzip_comp_level 6; 2.82,33686, 604 [ms], 100%
gzip_comp_level 7; 2.82,33626, 659 [ms], 100%
gzip_comp_level 8; 2.82,33626, 698 [ms], 100%
gzip_comp_level 9; 2.82,33626, 698 [ms], 100%

gzip_disable

通过表达式,表明哪些UA头不使用gzip压缩

Syntax: gzip_disable regex ...;
Default:    —
Context:    http, server, location
This directive appeared in version 0.6.23.

gzip_min_length

当返回内容大于此值时才会使用gzip进行压缩,以K为单位,当值为0时,所有页面都进行压缩。

Syntax: gzip_min_length length;
Default:    
gzip_min_length 20;
Context:    http, server, location

gzip_http_version

用于识别http协议的版本,早期的浏览器不支持gzip压缩,用户会看到乱码,所以为了支持前期版本加了此选项。默认在http/1.0的协议下不开启gzip压缩。

Syntax: gzip_http_version 1.0 | 1.1;
Default:    
gzip_http_version 1.1;
Context:    http, server, location

我看网上的很多文章中,对这一点都觉得过时了,因为浏览器基本上都支持HTTP/1.1。然而这里面却存在着一个很容易掉入的坑,也是笔者从生产环境中一个诡异问题中发现的:
问题背景:
笔者所在公司的静态资源服务器全部使用的Nginx,且都开启了gzip压缩。内部测试是完全正常的,然而一到外网,居然没有做gzip!

原因定位:
为什么这样呢?
在应用服务器前,公司还有一层Nginx的集群作为七层负责均衡,在这一层上,是没有开启gzip的。
如果我们使用了proxy_pass进行反向代理,那么nginx和后端的upstream server之间默认是用HTTP/1.0协议通信的。
如果我们的Cache Server也是nginx,而前端的nginx没有开启gzip。
同时,我们后端的nginx上没有设置gzip_http_version为1.0,那么Cache的url将不会进行gzip压缩。

我相信,以后还有人会入坑,比如你用Apache ab做压测,如果不是设置gzip_http_version为1.0,你也压不出gzip的效果(同样的道理)。希望写在这里对大家有帮助

gzip_proxied

Nginx做为反向代理的时候启用:

  • off – 关闭所有的代理结果数据压缩
  • expired – 如果header中包含”Expires”头信息,启用压缩
  • no-cache – 如果header中包含”Cache-Control:no-cache”头信息,启用压缩
  • no-store – 如果header中包含”Cache-Control:no-store”头信息,启用压缩
  • private – 如果header中包含”Cache-Control:private”头信息,启用压缩
  • no_last_modified – 启用压缩,如果header中包含”Last_Modified”头信息,启用压缩
  • no_etag – 启用压缩,如果header中包含“ETag”头信息,启用压缩
  • auth – 启用压缩,如果header中包含“Authorization”头信息,启用压缩
  • any – 无条件压缩所有结果数据
Syntax: gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any ...;
Default:    
gzip_proxied off;
Context:    http, server, location

gzip_types

设置需要压缩的MIME类型,如果不在设置类型范围内的请求不进行压缩

Syntax: gzip_types mime-type ...;
Default:    
gzip_types text/html;
Context:    http, server, location

这里需要说明一些特殊的类型,比如笔者公司会使用”字体类型”的资源,而这些资源类型往往会被忽略,且这些资源又比较大,没有被压缩很不合算。(可以参考:http://www.darrenfang.com/2015/01/setting-up-http-cache-and-gzip-with-nginx/):

所以MIME-TYPE中应该新增字体类型:

字体类型扩展名 Content-type
.eot application/vnd.ms-fontobject
.ttf font/ttf
.otf font/opentype
.woff font/x-woff
.svg image/svg+xml

gzip_vary

增加响应头”Vary: Accept-Encoding”

Syntax: gzip_vary on | off;
Default:    
gzip_vary off;
Context:    http, server, location

关于CentOS7下swap分区创建(添加),删除以及相关配置

小叨下背景:笔者的服务器内存只有1g,少得可怜。之前使用apache,不堪忍受其过量的内存消耗,网站卡得想哭,数据库也不断地崩,无奈投入nginx的怀抱并且已经喜欢上了nginx。

Linux 将物理内存分为内存段,叫做页面。交换是指内存页面被复制到预先设定好的硬盘空间(叫做交换空间)的过程,目的是释放对于页面的内存。物理内存和交换空间的总大小是可用的虚拟内存的总量。

Swap即:交换分区,类似于Windows的虚拟内存,但物理内存不足时,把部分硬盘空间当成虚拟内存使用,从而解决了物理内存容量不足。

优点:节省成本。缺点:性能不足。

这两天我那谁一直在折腾RedHat安装Oracle数据,该数据库有一项要求就是需要一定空间的swap分区。虽然早有耳闻swap分区,而且笔者经常折腾windows下的虚拟内存(swap和虚拟内存是类似概念),却很惭愧一直没想到这个办法,于是——进入今天的主题:

此方法不局限于Centos 7,Linux系统均可使用。

操作用户:root。

在添加swap分区之前我们可以了解下当前系统swap是否存在以及使用情况,可用:

free-h 或 swapon -s

了解硬盘使用情况(一般/dev/vda1为挂载硬盘):

df -hal

1.添加swap交换分区空间

dd命令

编辑dd是Linux/UNIX下的一个非常有用的命令,作用是用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。

确定硬盘的最佳块大小:

dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file

dd if=/dev/zero bs=2048 count=500000 of=/root/1Gb.file

dd if=/dev/zero bs=4096 count=250000 of=/root/1Gb.file

dd if=/dev/zero bs=8192 count=125000 of=/root/1Gb.file

通过比较以上命令输出中所显示的命令执行时间,即可确定系统最佳的块大小。

使用dd命令创建swap交换分区文件/dev/mapper/swap,大小为2G:

[root@vultr mapper]# dd if=/dev/zero of=/dev/mapper/swap bs=4096 count=512000

512000+0 records in
512000+0 records out
2097152000 bytes (2.1 GB) copied, 2.83708 s, 739 MB/s

[root@vultr mapper]#

格式化swap分区:

[root@vultr mapper]# mkswap /dev/mapper/swap

Setting up swapspace version 1, size = 2047996 KiB
no label, UUID=89015f83-f9ac-4a94-be51-6a6fb903ca4d

设置交换分区:

[root@vultr mapper]# mkswap -f /dev/mapper/swap

mkswap: /dev/mapper/swap: warning: wiping old swap signature.
Setting up swapspace version 1, size = 2047996 KiB
no label, UUID=be57a113-1838-4537-b0ef-d3c427f8295e

激活swap分区:

[root@vultr mapper]# swapon /dev/mapper/swap

swapon: /swap: insecure permissions 0644, 0600 suggested.

执行以上命令可能会出现:“不安全的权限0644,建议使用0600”类似提示,不要紧张,实际上已经激活了,可以忽略提示,也可以听从系统的建议修改下权限:

chmod -R 0600 /dev/mapper/swap

设为开机自动启用:

$ vim /etc/fstab

在该文件底部添加如下内容:

/dev/mapper/swap swap swap default 0 0

或直接对fstab进行echo追加:

echo “/dev/mapper/swapswap swap defaults 0 0”>> /etc/fstab

大功告成!

Centos7下增加swap分区大小

如果系统的物理内存用光了,系统就会跑得很慢,但仍能运行;如果Swap空间用光了,那么系统就会发生错误。例如,Swap空间用完,则服务进程无法启动,通常会出现“application is out of memory”的错误,严重时会造成服务进程的死锁。因此Swap空间的分配是很重要的,通常Swap空间的大小应是物理内存的2-2.5倍.

此方法不限于centos,linux均适用

以下命令均需在root帐号下操作

1.先用free -m查看一下swap的大小

2. 使用dd命令创建/home/swap这么一个分区文件。文件的大小是512000个block,一般情况下1个block为1K,所以这里空间是512M。

#dd if=/dev/zero of=/dev/mapper/swap bs=1024 count=512000

3.接着再把这个分区变成swap分区。

#/sbin/mkswap /dev/mapper/swap

4.再接着使用这个swap分区。使其成为有效状态。

#/sbin/swapon /dev/mapper/swap

现在再用free -m命令查看一下内存和swap分区大小,就发现增加了512M的空间了。

删除某swap分区

先停止正在使用swap分区:

swapoff /dev/mapper/swap

删除swap分区文件

rm -rf /dev/mapper/swap

删除或注释掉我们之前在fstab文件里追加的开机自动挂载配置内容:/dev/mapper/swapswap swap defaults 0 0
3.更改Swap配置(进阶级)
swappiness值(0-100),系统对swap分区的依赖程度,越高则越倾向于使用swap分区。当然,高度依赖swap会造成物理内存远未使用完,就使用swap分区,我们知道swap分区性能远不如物理内存,这反而降低了系统性能,违背了我们创建swap分区的初衷。我们希望在物理内存即将满荷时再使用swap,这就决定了swappiness值一般为10-60为宜,固态硬盘可以偏高些。查看当前的swappiness数值:

cat /proc/sys/vm/swappiness

修改swappiness值,这里以50为例。

sysctl vm.swappiness=50

若希望vm.swappiness=50永久生效,则需要修改sysctl配置文件,直接echo追加配置内容,重启系统后即可生效:

echo “vm.swappiness = 50”>> /etc/sysctl.conf