标签归档:linux

CentOS 7 修复官方源/更换阿里云yum镜像源

发现即使在国外节点的服务器,阿里云的centos镜像源速度仍然是不讲道理的下载速度,对比原来的centos官方的源的速度,快N倍。
果断换掉破自行车,换飞机。
删除centos官方源前,请确保已经安装了wget命令,如果已经删源了还没安装wget,可以先恢复官方源,安装wget再删除官方源。

  • 恢复官方源:rpm -Uvh –force http://mirror.centos.org/centos-7/7/os/x86_64/Packages/centos-release-7-9.2009.0.el7.centos.x86_64.rpm 备注:由于rpm包跟着最新版更新,具体以官网现有的rpm包名字的链接为准,我现在的时间最新版为7.7.1908,如果安装官方报错,可以自行到源站查看最新版包名,把url中的centos-release-7-7.1908.0.el7.centos.x86_64.rpm相应版本号改成你在官网看到的版本号即可
  • 安装wget
    yum install -y wget
    安装wget之后,就可以把centos官方源换成阿里的。
  1. 清除yum缓存yum clean all
  2. 删除官方源cd /etc/yum.repos.d && rm -rf ./*
  3. 添加阿里云的镜像源和EPEL源
  4. 重新生成缓存yum makecache & yum makecache fast
  5. 更新软件包,系统yum update -y
  6. 享受阿里云遍布全球的CDN加速节点

Linux使用unzip命令解压其中的部分文件到指定文件夹

相信很多人都遇到过Candy的情况:

公司电商平台备份后文件大小多达10个G!海量小文件、图片、js、css等等……;

这造成了一种情况,如果不小心删除了一个文件而无法恢复的情况! 那就只能从备份文件中提取咯! 但是一想到为了提取几KB的一个文件,而unzip整个压缩文件。



请谨记以下命令:

unzip <Your zip file> “*mobile/要解压的文件” -d <要解压的目录>

如:unzip www.dnsdizhi.com.zip “Nginx/* ” Nginx/

* : 可以使用*做通配符,具体使用我就不废话了!
-d : -d 参数后面跟上你要解压文件到哪个目录;

xfs文件删除没有释放,系统重启还是没有释放

XFS文件系统管理常用命令记录

xfs_fsr /dev/vda1 单用户模式后,用碎片整理好恢复正常。

常用命令说明

mkfs.xfs
创建xfs文件系统
xfs_admin
调整XFS文件系统各种参数
xfs_copy
并行地拷贝XFS文件系统的内容到一个或多个目标系统中
xfs_db
调试或检测XFS文件系统
xfs_check
检测XFS文件系统完整性
xfs_bmap
查看一个文件的块映射
xfs_repair
尝试修复受损的XFS文件系统
xfs_fsr
碎片整理
xfs_quota
管理XFS文件系统的磁盘配额
xfs_metadump
导出XFS文件系统的元数据
xfs_growfs
扩展XFS文件系统大小
xfs_freeze
暂停/恢复XFS文件系统

创建XFS文件系统

使用 mkfs.xfs 可以将存储设备格式化为XFS格式

dd if=/dev/zero of=~/xfs.img bs=1M count=4096
mkfs.xfs ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=4096   blocks=1048576, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

但若原存储已经被格式化过,则 mkfs.xfs 会拒绝再次格式化

mkfs.xfs ~/xfs.img 2>&1 ||exit 0

mkfs.xfs: /home/lujun9972/xfs.img appears to contain an existing filesystem (xfs).
mkfs.xfs: Use the -f option to force overwrite.

这个时候需要用 -f 选项表示强行格式化

mkfs.xfs -f ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=4096   blocks=1048576, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

设置block大小

block是文件系统存储的最小单位,较大的block可以增加文件系统和单个文件的大小上限并加快大文件的读写速度,但是会浪费较多空间。而太小的block则相反。

我们可以在格式化时指定block的大小,XFS的大小最小为512字节,最大为64KB,默认为4K

在格式化时使用 -b size=block大小 来指定区块大小

mkfs.xfs -f -b size=1k ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=1048576 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=1024   blocks=4194304, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=1024   blocks=10240, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

这里大小单位可以是”k”表示kb,或者”s”表示扇区数,一个扇区默认为512字节,但可以通过 -s 选项改变。

XFS允许目录使用比文件系统block更大的block,方法是使用 -n size=block大小

mkfs.xfs -f -b size=1k -n size=4k ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=1048576 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=1024   blocks=4194304, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=1024   blocks=10240, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

日志大小

格式化XFS时,mkfs.xfs会根据文件系统的大小自动分配日志的大小。 日志大小介于512KB到128MB之间,但可以通过 -l size=日志大小 来设置,其中日志的单位可以是:

s
扇区
b
block
k
KB
m
MB
g
GB
t
TB
p
PB
e
EB
mkfs.xfs -f -l size=64m ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=4096   blocks=1048576, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=16384, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

设置文件系统标签

Label或者说Volume Name可以用来说明文件系统的用途,可以通过 -L 标签 来设置

mkfs.xfs -f -L TEST ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=4096   blocks=1048576, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

我们可以使用 xfs_admin 来查看当前的label

xfs_admin -l ~/xfs.img

label = "TEST"

挂载XFS文件系统

在挂载时,可以使用一些性能增强的选项来发掘XFS文件系统的性能

sudo mount -t xfs ~lujun9972/xfs.img /mnt -o noatime,nodiratime

其他常见的 -o 选项包括:

allocsize
延时分配时,预分配缓冲区的大小
discard / nodiscard
块设备是否自动回收空间
largeio
大块分配
nolargeio
尽量小块分配
noatime
读取文件时不更新访问时间
nodiratime
不更新目录的访问时间
norecovery
挂载时不运行日志恢复
logbufs
内存中的日志缓冲区数量
logbsize
内存中每个日志缓存区的大小

调整XFS文件系统参数

使用 xfs_admin 来调整XFS文件系统参数

卷标管理

设置卷标

xfs_admin -L "another_volume" ~/xfs.img

writing all SBs
xfs_admin: truncating label length from 14 to 12
new label = "another_volu"

查看卷标

xfs_admin -l ~/xfs.img

label = "another_volu"

UUID管理

传统上Linux在/etc/fstab中直接使用设备名称指定要挂载的存储设备。 然而设备名称会因为BIOS或硬件的改变而改变,引起混乱,因此现在Linux改用UUID来指定要挂载的存储设备。

查看指定设备的UUID

xfs_admin -u ~/xfs.img

UUID = aceeca47-82a0-47ce-a2e6-704569ebcbd4

设置设备的UUID

xfs_admin -U 12345678-9012-3456-7890-123456789012 ~/xfs.img

Clearing log and setting UUID
writing all SBs
new UUID = 12345678-9012-3456-7890-123456789012

你也可以给 -U 参数传递 generate 表示随机生成新的UUID

xfs_admin -U generate ~/xfs.img

Clearing log and setting UUID
writing all SBs
new UUID = 9618fe39-638d-41b0-9863-5b3b8daa9801

清除文件系统的UUID

xfs_admin -U nil ~/xfs.img

Clearing log and setting UUID
writing all SBs
new UUID = 00000000-0000-0000-0000-000000000000

扩展XFS文件系统的大小

XFS文件系统只能扩大,不能减少大小

扩容指定容量

sudo xfs_growfs -D 20G /mnt

扩展全部未用容量

sudo xfs_growfs -d /mnt

暂停/恢复XFS文件系统

xfs_freeze 命令可以停止对文件系统的访问并创建一个静态的磁盘镜像。

暂停XFS文件系统

sudo xfs_freeze -f /mnt

这个时候任何对文件系统的操作都会被挂起

恢复XFS文件系统

sudo xfs_freeze -u /mnt

修复XFS文件系统

sudo umount /mnt
xfs_repair ~lujun9972/xfs.img

碎片管理

查看碎片情况

xfs_db -c frag -r ~/xfs.img

actual 0, ideal 0, fragmentation factor 0.00%
Note, this number is largely meaningless.
Files on this filesystem average -nan extents per file

整理碎片

xfs_fsr ~/xfs.img

linux系统收到SYN但不回SYN+ACK问题排查

wKioL1mKiFzyAHTYAAZzy5AQiS4317.jpg

二,排查

1,发现系统没有任何负载

2,网卡也没有丢包

3,iptables策略也都没问题

4,系统的SYN_RECV连接很少,也没超限

5,系统的文件描述符等资源也都没问题

6,messages和dmesg中没有任何提示或者错误信息

7,通过netstat命令查看系统上协议统计信息,发现很多请求由于时间戳的问题被rejected

# netstat -s |grep reject
    2181 passive connections rejected because of time stamp
    34 packets rejects in established connections because of timestamp

三,通过google来协助

发现有同样的人遇见这个问题:

是通过调整sysctl -w net.ipv4.tcp_timestamps=0或者sysctl -w net.ipv4.tcp_tw_recycle=0来解决这个问题,于是我就顺藤摸瓜继续查。

而在查询这两个参数的过程中,发现问题原因如下:

发现是 Linux tcp_tw_recycle/tcp_timestamps设置导致的问题。 因为在linux kernel源码中发现tcp_tw_recycle/tcp_timestamps都开启的条件下,60s内同一源ip主机的socket connect请求中的timestamp必须是递增的。经过测试,我这边centos6系统(kernel 2.6.32)和centos7系统(kernel 3.10.0)都有这问题。

    源码函数:kernel 2.6.32 tcp_v4_conn_request(),该函数是tcp层三次握手syn包的处理函数(服务端);
    源码片段:
       if (tmp_opt.saw_tstamp &&
            tcp_death_row.sysctl_tw_recycle &&
            (dst = inet_csk_route_req(sk, req)) != NULL &&
            (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
            peer->v4daddr == saddr) {
            if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
                (s32)(peer->tcp_ts – req->ts_recent) >
                            TCP_PAWS_WINDOW) {
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
                goto drop_and_release;
            }
        }
        
        tmp_opt.saw_tstamp:该socket支持tcp_timestamp
        sysctl_tw_recycle:本机系统开启tcp_tw_recycle选项
        TCP_PAWS_MSL:60s,该条件判断表示该源ip的上次tcp通讯发生在60s内
        TCP_PAWS_WINDOW:1,该条件判断表示该源ip的上次tcp通讯的timestamp 大于 本次tcp

总结:

我这边和其它同事通过公司出口(NAT网关只有1个ip地址)访问问题server,由于timestamp时间为系统启动到当前的时间,故我和其它同事的timestamp肯定不相同;根据上述SYN包处理源码,在tcp_tw_recycle和tcp_timestamps同时开启的条件下,timestamp大的主机访问serverN成功,而timestmap小的主机访问失败。并且,我在办公网找了两台机器可100%重现这个问题。

解决:

# echo “0” > /proc/sys/net/ipv4/tcp_tw_recycle

四,扩展

1,net.ipv4.tcp_timestamps

tcp_timestamps的本质是记录数据包的发送时间。基本的步骤如下:

发送方在发送数据时,将一个timestamp(表示发送时间)放在包里面

接收方在收到数据包后,在对应的ACK包中将收到的timestamp返回给发送方(echo back)

发送发收到ACK包后,用当前时刻now – ACK包中的timestamp就能得到准确的RTT

当然实际运用中要考虑到RTT的波动,因此有了后续的(Round-Trip Time Measurement)RTTM机制。

TCP Timestamps Option (TSopt)具体设计如下

Kind: 8             // 标记唯一的选项类型,比如window scale是3
Length: 10 bytes    // 标记Timestamps选项的字节数
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| Kind=8 | Length=10 | TS Value (TSval) | TS ECho Reply (TSecr) |
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
   1          1             4                       4
timestamps一个双向的选项,当一方不开启时,两方都将停用timestamps。比如client端发送的SYN包中带有timestamp选项,但server端并没有开启该选项。则回复的SYN-ACK将不带timestamp选项,同时client后续回复的ACK也不会带有timestamp选项。当然,如果client发送的SYN包中就不带timestamp,双向都将停用timestamp。

tcp数据包中timestamps的value是系统开机时间到现在时间的(毫秒级)时间戳。

参数:

0:停用

1:启用(系统默认值)

2,net.ipv4.tcp_tw_recycle

TCP规范中规定的处于TIME_WAIT的TCP连接必须等待2MSL时间。但在linux中,如果开启了tcp_tw_recycle,TIME_WAIT的TCP连接就不会等待2MSL时间(而是rto或者60s),从而达到快速重用(回收)处于TIME_WAIT状态的tcp连接的目的。这就可能导致连接收到之前连接的数据。为此,linux在打开tcp_tw_recycle的情况下,会记录下TIME_WAIT连接的对端(peer)信息,包括IP地址、时间戳等。这样,当内核收到同一个IP的SYN包时,就会去比较时间戳,检查SYN包的时间戳是否滞后,如果滞后,就将其丢掉(认为是旧连接的数据)。这在绝大部分情况下是没有问题的,但是对于我们实际的client-server的服务,访问我们服务的用户一般都位于NAT之后,如果NAT之后有多个用户访问同一个服务,就有可能因为时间戳滞后的连接被丢掉。

参数:

0:停用(系统默认值)

1:启用

参考:

https://serverfault.com/questions/235965/why-would-a-server-not-send-a-syn-ack-packet-in-response-to-a-syn-packet

http://hustcat.github.io/tcp_tw_recycle-and-tcp_timestamp/

linux free 查询可用内存

free工具用来查看系统可用内存:

/opt/app/tdev1$free
             total       used       free     shared    buffers     cached
Mem:       8175320    6159248    2016072          0     310208    5243680
-/+ buffers/cache:     605360    7569960
Swap:      6881272      16196    6865076

解释一下Linux上free命令的输出。

下面是free的运行结果,一共有4行。为了方便说明,我加上了列号。这样可以把free的输出看成一个二维数组FO(Free Output)。例如:

FO[2][1] = 24677460 FO[3][2] = 10321516 1 2 3 4 5 6 1 total used free shared buffers cached 2 Mem: 24677460 23276064 1401396 0 870540 12084008 3 -/+ buffers/cache: 10321516 14355944 4 Swap: 25151484 224188 24927296 

free的输出一共有四行,第四行为交换区的信息,分别是交换的总量(total),使用量(used)和有多少空闲的交换区(free),这个比较清楚,不说太多。

free输出地第二行和第三行是比较让人迷惑的。这两行都是说明内存使用情况的。第一列是总量(total),第二列是使用量(used),第三列是可用量(free)。

第一行的输出时从操作系统(OS)来看的。也就是说,从OS的角度来看,计算机上一共有:

24677460KB(缺省时free的单位为KB)物理内存,即FO[2][1]; 在这些物理内存中有23276064KB(即FO[2][2])被使用了; 还用1401396KB(即FO[2][3])是可用的;

这里得到第一个等式:

FO[2][1] = FO[2][2] + FO[2][3]

FO[2][4]表示被几个进程共享的内存的,现在已经deprecated,其值总是0(当然在一些系统上也可能不是0,主要取决于free命令是怎么实现的)。

FO[2][5]表示被OS buffer住的内存。FO[2][6]表示被OS cache的内存。在有些时候buffer和cache这两个词经常混用。不过在一些比较低层的软件里是要区分这两个词的,看老外的洋文:

A buffer is something that has yet to be "written" to disk. A cache is something that has been "read" from the disk and stored for later use. 

也就是说buffer是用于存放要输出到disk(块设备)的数据的,而cache是存放从disk上读出的数据。这二者是为了提高IO性能的,并由OS管理。

Linux和其他成熟的操作系统(例如windows),为了提高IO read的性能,总是要多cache一些数据,这也就是为什么FO[2][6](cached memory)比较大,而FO[2][3]比较小的原因。我们可以做一个简单的测试:

释放掉被系统cache占用的数据:

echo 3>/proc/sys/vm/drop_caches 

  1. 读一个大文件,并记录时间;
  2. 关闭该文件;
  3. 重读这个大文件,并记录时间;

第二次读应该比第一次快很多。原来我做过一个BerkeleyDB的读操作,大概要读5G的文件,几千万条记录。在我的环境上,第二次读比第一次大概可以快9倍左右。

free输出的第二行是从一个应用程序的角度看系统内存的使用情况。

  • 对于FO[3][2],即-buffers/cache,表示一个应用程序认为系统被用掉多少内存;
  • 对于FO[3][3],即+buffers/cache,表示一个应用程序认为系统还有多少内存;

因为被系统cache和buffer占用的内存可以被快速回收,所以通常FO[3][3]比FO[2][3]会大很多。

这里还用两个等式:

FO[3][2] = FO[2][2] - FO[2][5] - FO[2][6] FO[3][3] = FO[2][3] + FO[2][5] + FO[2][6] 

这二者都不难理解。

free命令由procps.*.rpm提供(在Redhat系列的OS上)。free命令的所有输出值都是从/proc/meminfo中读出的。

在系统上可能有meminfo(2)这个函数,它就是为了解析/proc/meminfo的。procps这个包自己实现了meminfo()这个函数。可以下载一个procps的tar包看看具体实现,现在最新版式3.2.8。

文章出处:

http://www.cnblogs.com/coldplayerest/archive/2010/02/20/1669949.html

free命令可以显示Linux系统中空闲的、已用的物理内存及swap内存,及被内核使用的buffer。在Linux系统监控的工具中,free命令是最经常使用的命令之一。

1.命令格式:

free [参数]

2.命令功能:

free 命令显示系统使用和空闲的内存情况,包括物理内存、交互区内存(swap)和内核缓冲区内存。共享内存将被忽略

3.命令参数:

-b  以Byte为单位显示内存使用情况。 

-k  以KB为单位显示内存使用情况。 

-m  以MB为单位显示内存使用情况。

-g   以GB为单位显示内存使用情况。 

-o  不显示缓冲区调节列。 

-s<间隔秒数>  持续观察内存使用状况。 

-t  显示内存总和列。 

-V  显示版本信息。 

4.使用实例:

实例1:显示内存使用情况

命令:

free

free -g

free –m

输出:

[root@SF1150 service]# free

             total       used       free     shared    buffers     cached

Mem:      32940112   30841684    2098428          0    4545340   11363424

-/+ buffers/cache:   14932920   18007192

Swap:     32764556    1944984   30819572

[root@SF1150 service]# free -g

             total       used       free     shared    buffers     cached

Mem:            31         29          2          0          4         10

-/+ buffers/cache:         14         17

Swap:           31          1         29

[root@SF1150 service]# free -m

             total       used       free     shared    buffers     cached

Mem:         32168      30119       2048          0       4438      11097

-/+ buffers/cache:      14583      17584

Swap:        31996       1899      30097

说明:

下面是对这些数值的解释:

total:总计物理内存的大小。

used:已使用多大。

free:可用有多少。

Shared:多个进程共享的内存总额。

Buffers/cached:磁盘缓存的大小。

第三行(-/+ buffers/cached):

used:已使用多大。

free:可用有多少。

第四行是交换分区SWAP的,也就是我们通常所说的虚拟内存。

区别:第二行(mem)的used/free与第三行(-/+ buffers/cache) used/free的区别。 这两个的区别在于使用的角度来看,第一行是从OS的角度来看,因为对于OS,buffers/cached 都是属于被使用,所以他的可用内存是2098428KB,已用内存是30841684KB,其中包括,内核(OS)使用+Application(X, oracle,etc)使用的+buffers+cached.

第三行所指的是从应用程序角度来看,对于应用程序来说,buffers/cached 是等于可用的,因为buffer/cached是为了提高文件读取的性能,当应用程序需在用到内存的时候,buffer/cached会很快地被回收。

所以从应用程序的角度来说,可用内存=系统free memory+buffers+cached。

如本机情况的可用内存为:

18007156=2098428KB+4545340KB+11363424KB

接下来解释什么时候内存会被交换,以及按什么方交换。 

当可用内存少于额定值的时候,就会开会进行交换.如何看额定值: 

命令:

cat /proc/meminfo 

输出:

[root@SF1150 service]# cat /proc/meminfo

MemTotal:     32940112 kB

MemFree:       2096700 kB

Buffers:       4545340 kB

Cached:       11364056 kB

SwapCached:    1896080 kB

Active:       22739776 kB

Inactive:      7427836 kB

HighTotal:           kB

HighFree:            kB

LowTotal:     32940112 kB

LowFree:       2096700 kB

SwapTotal:    32764556 kB

SwapFree:     30819572 kB

Dirty:             164 kB

Writeback:           kB

AnonPages:    14153592 kB

Mapped:          20748 kB

Slab:           590232 kB

PageTables:      34200 kB

NFS_Unstable:        kB

Bounce:              kB

CommitLimit:  49234612 kB

Committed_AS: 23247544 kB

VmallocTotal: 34359738367 kB

VmallocUsed:    278840 kB

VmallocChunk: 34359459371 kB

HugePages_Total:     0HugePages_Free:      0HugePages_Rsvd:      0Hugepagesize:     2048 kB

交换将通过三个途径来减少系统中使用的物理页面的个数:  

1.减少缓冲与页面cache的大小, 

2.将系统V类型的内存页面交换出去,  

3.换出或者丢弃页面。(Application 占用的内存页,也就是物理内存不足)。 

事实上,少量地使用swap是不是影响到系统性能的。

那buffers和cached都是缓存,两者有什么区别呢?

为了提高磁盘存取效率, Linux做了一些精心的设计, 除了对dentry进行缓存(用于VFS,加速文件路径名到inode的转换), 还采取了两种主要Cache方式:Buffer Cache和Page Cache。前者针对磁盘块的读写,后者针对文件inode的读写。这些Cache有效缩短了 I/O系统调用(比如read,write,getdents)的时间。

磁盘的操作有逻辑级(文件系统)和物理级(磁盘块),这两种Cache就是分别缓存逻辑和物理级数据的。

Page cache实际上是针对文件系统的,是文件的缓存,在文件层面上的数据会缓存到page cache。文件的逻辑层需要映射到实际的物理磁盘,这种映射关系由文件系统来完成。当page cache的数据需要刷新时,page cache中的数据交给buffer cache,因为Buffer Cache就是缓存磁盘块的。但是这种处理在2.6版本的内核之后就变的很简单了,没有真正意义上的cache操作。

Buffer cache是针对磁盘块的缓存,也就是在没有文件系统的情况下,直接对磁盘进行操作的数据会缓存到buffer cache中,例如,文件系统的元数据都会缓存到buffer cache中。

简单说来,page cache用来缓存文件数据,buffer cache用来缓存磁盘数据。在有文件系统的情况下,对文件操作,那么数据会缓存到page cache,如果直接采用dd等工具对磁盘进行读写,那么数据会缓存到buffer cache。

所以我们看linux,只要不用swap的交换空间,就不用担心自己的内存太少.如果常常swap用很多,可能你就要考虑加物理内存了.这也是linux看内存是否够用的标准.

如果是应用服务器的话,一般只看第二行,+buffers/cache,即对应用程序来说free的内存太少了,也是该考虑优化程序或加内存了。

实例2:以总和的形式显示内存的使用信息

命令:

  free -t 

输出:

[root@SF1150 service]#  free -t 

             total       used       free     shared    buffers     cached

Mem:      32940112   30845024    2095088          0    4545340   11364324

-/+ buffers/cache:   14935360   18004752Swap:     32764556    1944984   30819572Total:    65704668   32790008   32914660[root@SF1150 service]#

说明:

实例3:周期性的查询内存使用信息

命令:

free -s 10

输出:

[root@SF1150 service]#  free -s 10

             total       used       free     shared    buffers     cached

Mem:      32940112   30844528    2095584          0    4545340   11364380

-/+ buffers/cache:   14934808   18005304Swap:     32764556    1944984   30819572

             total       used       free     shared    buffers     cached

Mem:      32940112   30843932    2096180          0    4545340   11364388

-/+ buffers/cache:   14934204   18005908Swap:     32764556    1944984   30819572

说明:

每10s 执行一次命令

https://www.cnblogs.com/peida/archive/2012/12/25/2831814.html

linux 百万并发连接之内核优化tcp_mem

在服务端,连接达到一定数量,诸如50W时,有些隐藏很深的问题,就不断的抛出来。 通过查看dmesg命令查看,发现大量TCP: too many of orphaned sockets错误,也很正常,下面到了需要调整tcp socket参数的时候了。

第一个需要调整的是tcp_rmem,即TCP读取缓冲区,单位为字节,查看默认值

  1. cat /proc/sys/net/ipv4/tcp_rmem
  2. 4096 87380 4161536

默认值为87380 byte ≈ 86K,最小为4096 byte=4K,最大值为4064K。

第二个需要调整的是tcp_wmem,发送缓冲区,单位是字节,默认值

  1. cat /proc/sys/net/ipv4/tcp_wmem
  2. 4096 16384 4161536

解释同上

第三个需要调整的tcp_mem,调整TCP的内存大小,其单位是页,1页等于4096字节。系统默认值:

  1. cat /proc/sys/net/ipv4/tcp_mem
  2. 932448 1243264 1864896

tcp_mem(3个INTEGER变量):low, pressure, high

  • low:当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存。
  • pressure:当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态。
  • high:允许所有tcp sockets用于排队缓冲数据报的页面量,当内存占用超过此值,系统拒绝分配socket,后台日志输出“TCP: too many of orphaned sockets”。

一般情况下这些值是在系统启动时根据系统内存数量计算得到的。 根据当前tcp_mem最大内存页面数是1864896,当内存为(1864896*4)/1024K=7284.75M时,系统将无法为新的socket连接分配内存,即TCP连接将被拒绝。

实际测试环境中,据观察大概在99万个连接左右的时候(零头不算),进程被杀死,触发out of socket memory错误(dmesg命令查看获得)。每一个连接大致占用7.5K内存(下面给出计算方式),大致可算的此时内存占用情况(990000 * 7.5 / 1024K = 7251M)。

这样和tcp_mem最大页面值数量比较吻合,因此此值也需要修改。

三个TCP调整语句为:

  1. echo “net.ipv4.tcp_mem = 786432 2097152 3145728”>> /etc/sysctl.conf
  2. echo “net.ipv4.tcp_rmem = 4096 4096 16777216”>> /etc/sysctl.conf
  3. echo “net.ipv4.tcp_wmem = 4096 4096 16777216”>> /etc/sysctl.conf

备注: 为了节省内存,设置tcp读、写缓冲区都为4K大小,tcp_mem三个值分别为3G 8G 16G,tcp_rmemtcp_wmem最大值也是16G。

目标达成

经过若干次的尝试,最终达到目标,1024000个持久连接。1024000数字是怎么得来的呢,两台物理机器各自发出64000个请求,两个配置为6G左右的centos测试端机器(绑定7个桥接或NAT连接)各自发出640007 = 448000。也就是 1024000 = (64000) + (64000) + (640007) + (64000*7), 共使用了16个网卡(物理网卡+虚拟网卡)。
终端输出

  1. ……
  2. online user 1023990
  3. online user 1023991
  4. online user 1023992
  5. online user 1023993
  6. online user 1023994
  7. online user 1023995
  8. online user 1023996
  9. online user 1023997
  10. online user 1023998
  11. online user 1023999
  12. online user 1024000

在线用户目标达到1024000个!

服务器状态信息

服务启动时内存占用:

  1. total used free shared buffers cached
  2. Mem: 10442 271 10171 0 22 78
  3. -/+ buffers/cache: 171 10271
  4. Swap: 8127 0 8127

系统达到1024000个连接后的内存情况(执行三次 free -m 命令,获取三次结果):

  1. total used free shared buffers cached
  2. Mem: 10442 7781 2661 0 22 78
  3. -/+ buffers/cache: 7680 2762
  4. Swap: 8127 0 8127
  5. total used free shared buffers cached
  6. Mem: 10442 7793 2649 0 22 78
  7. -/+ buffers/cache: 7692 2750
  8. Swap: 8127 0 8127
  9. total used free shared buffers cached
  10. Mem: 10442 7804 2638 0 22 79
  11. -/+ buffers/cache: 7702 2740
  12. Swap: 8127 0 8127

这三次内存使用分别是7680,7692,7702,这次不取平均值,取一个中等偏上的值,定为7701M。那么程序接收1024000个连接,共消耗了 7701M-171M = 7530M内存, 7530M*1024K / 1024000 = 7.53K, 每一个连接消耗内存在为7.5K左右,这和在连接达到512000时所计算较为吻合。
虚拟机运行Centos内存占用,不太稳定,但一般相差不大,以上数值,仅供参考。

执行top -p 某刻输出信息:

  1. top – 17:23:17 up 18 min, 4 users, load average: 0.33, 0.12, 0.11
  2. Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
  3. Cpu(s): 0.2%us, 6.3%sy, 0.0%ni, 80.2%id, 0.0%wa, 4.5%hi, 8.8%si, 0.0%st
  4. Mem: 10693580k total, 6479980k used, 4213600k free, 22916k buffers
  5. Swap: 8323056k total, 0k used, 8323056k free, 80360k cached
  6. PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
  7. 2924 yongboy 20 0 82776 74m 508 R 51.3 0.7 3:53.95 server

执行vmstate:

  1. vmstat
  2. procs ———–memory———- —swap– —–io—- –system– —–cpu—–
  3. r b swpd free buff cache si so bi bo in cs us sy id wa st
  4. 0 0 0 2725572 23008 80360 0 0 21 2 1012 894 0 9 89 2 0

获取当前socket连接状态统计信息:

  1. cat /proc/net/sockstat
  2. sockets: used 1024380
  3. TCP: inuse 1024009 orphan 0 tw 0 alloc 1024014 mem 2
  4. UDP: inuse 11 mem 1
  5. UDPLITE: inuse 0
  6. RAW: inuse 0
  7. FRAG: inuse 0 memory 0

获取当前系统打开的文件句柄:

  1. sysctl -a | grep file
  2. fs.file-nr = 1025216 0 1048576
  3. fs.file-max = 1048576

此时任何类似于下面查询操作都是一个慢,等待若干时间还不见得执行完毕。

  1. netstat -nat|grep -i “8000”|grep ESTABLISHED|wc -l
  2. netstat -n | grep -i “8000” | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

以上两个命令在二三十分钟过去了,还未执行完毕,只好停止。

小结

本次从头到尾的测试,所需要有的linux系统需要调整的参数也就是那么几个,汇总一下:

  1. echo “* – nofile 1048576” >> /etc/security/limits.conf
  2. echo “fs.file-max = 1048576” >> /etc/sysctl.conf
  3. echo “net.ipv4.ip_local_port_range = 1024 65535” >> /etc/sysctl.conf
  4. echo “net.ipv4.tcp_mem = 786432 2097152 3145728” >> /etc/sysctl.conf
  5. echo “net.ipv4.tcp_rmem = 4096 4096 16777216” >> /etc/sysctl.conf
  6. echo “net.ipv4.tcp_wmem = 4096 4096 16777216” >> /etc/sysctl.conf

其它没有调整的参数,仅仅因为它们暂时对本次测试没有带来什么影响,实际环境中需要结合需要调整类似于SO_KEEPALIVE、tcpmax_orphans等大量参数。

cento6 下载源码升级curl到7.62.0

cento6 下载源码升级curl到7.62.0

由于业务需要,服务器上的curl 版本太老了,有漏洞,于是抽点时间升级最新版本,确保服务器间通信安全,然后网上看了些教程,发现各不相同,最后找到一个最简单,最方便的方法,分享给大家。

wget https://curl.haxx.se/download/curl-7.62.0.tar.gz

tar -zxvf curl-7.62.0.tar.gz

cd curl-7.62.0

./configure

make && make install

curl -V

git服务器bitnami-gitlab一键安装

github使用也有一段时间了,github上的内容都是公开的,要私有必须掏钱,github的服务器都在国外,下载也比较慢。如果公司内容使用肯定是不行的,之前没有自己搭建过git的服务器,今天决定试试,在网上找资料也找了半天,发现有一个快速安装github服务器bitnami的一键安装包

废话不多说开始操作

https://bitnami.com/stack/gitlab/installer

在上面的地址下载软件,我下载的版本是bitnami-gitlab-8.2.3-4-linux-installer.run

下载安装

wget https://bitnami.com/redirect/to/87432/bitnami-gitlab-8.2.3-4-linux-installer.run chmod 755 bitnami-gitlab-8.2.3-4-linux-installer.run ./bitnami-gitlab-8.2.3-4-linux-installer.run

开始配置

是否安装PhpPgAdmin,我选择是

是否安装PhpPgAdmin

上面的选择是否正确,没有问题输入Y

确认配置

选择安装目录,我直接输入回车,默认安装目录/opt/gitlab-8.2.3-4

bitnami选择安装目录

创建管理员

输入邮件、用户名、密码,注意密码必须是8位,我只输入了6,会警告,会重新创建

bitnami配置管理员账号

下面设置访问的域名,默认是80端口,第二项选择是否支持邮件,我这选择y

配置域名

开始邮件配置,我选择是gmail,配置了一个smtp

配置邮件

是否开始安装输入Y 开始安装

确认安装

使用帮助

在安装目录下有README.txt,里面有详细的使用说明

安装的服务 – GitLab 8.2.3 – Apache 2.4.18 – ImageMagick 6.7.5 – PostgreSQL 9.4.5 – Git 2.6.1 – Ruby 2.1.8 – Rails 4.2.4 – RubyGems 1.8.12 开始关闭重启相关服务 ./ctlscript.sh (start|stop|restart) ./ctlscript.sh (start|stop|restart) postgres ./ctlscript.sh (start|stop|restart) redis ./ctlscript.sh (start|stop|restart) apache ./ctlscript.sh (start|stop|restart) sidekiq

其他的自己看一下

sed和awk等方法实现列转成行

sed和awk等方法实现列转成行,当然只是很基础的东西,平时我遇到的问题会把它们整理到一起,然后对比分析,这样印象会更深刻。

[root@localhost ~]# cat file 

1

2

3

4

5

6

7

8

9

10

11

先把列转成行,写了5方法:

1.xargs实现

[root@localhost ~]# cat file |xargs

1 2 3 4 5 6 7 8 9 10 11

2.tr替换实现,需要echo换行

[root@localhost ~]# cat file |tr “\n” ” ” ;echo

1 2 3 4 5 6 7 8 9 10 11 

3.awk实现,ORS默认是换行符”\n”。

[root@localhost ~]# awk ‘{ORS=” “;print}’ file;echo

1 2 3 4 5 6 7 8 9 10 11

[root@localhost ~]# awk ‘{if(NR%11){ORS=” “}else{ORS=”\n”};print}’ file 

1 2 3 4 5 6 7 8 9 10 11

[root@localhost ~]# awk ‘ORS=NR%11?” “:”\n”{print}’ file

1 2 3 4 5 6 7 8 9 10 11

4.perl实现

[root@localhost ~]# cat file |perl -pe ‘s/\n/ /’ ;echo

1 2 3 4 5 6 7 8 9 10 11

5.sed是用N实现。N:将当前行的下一行数据追加进当前模式空间,然后将换行符替换成空格。

[root@localhost ~]# cat file |sed ‘N;N;N;N;N;N;N;N;N;N;s/\n/ /g’

1 2 3 4 5 6 7 8 9 10 11

有一个源文件:

[root@localhost ~]# cat filename

00000 –caipiao

123291

234234

546237

11111 –zhuce

456457

678768

432345

想要的结果:

00000 123291|234234|546237

11111 456457|678768|432345

实现方法:

这句话是通过改变 输出的 记录分隔符ORS 来实现的,ORS默认是换行符”\n”

NR是当前的行号,用NR%4取余,分隔成2行内容, 如果是则将ORS赋值为”|” ,否则赋值为”\n”,用的是一个三元操作 A?B:C   满足A则B否则C 

也可以写成awk ‘if(NR%4){ORS=”|”}else{ORS=”\n”}’

[root@localhost ~]# awk ‘{print $1}’ filename |awk ‘ORS=NR%4?”|”:”\n”{print}’ |sed ‘s/|/ /’

00000 123291|234234|546237

11111 456457|678768|432345

[root@localhost ~]#awk ‘{print $1}’ filename |awk ‘{if(NR%4){ORS=”|”}else{ORS=”\n”};print}’ |sed ‘s/|/ /’

00000 123291|234234|546237

11111 456457|678768|432345

[root@localhost ~]# awk ‘{print $1}’ filename |sed ‘N;N;N;s/\n/ /g’ |sed ‘s/ /|/g’ |sed ‘s/|/ /’

00000 123291|234234|546237

11111 456457|678768|432345