centos not enough?centos7卸载软件命令
本篇文章给大家谈谈centos not enough,以及centos7卸载软件命令对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。
Linux系统的OOM Killer处理机制
最近有位 VPS客户抱怨 MySQL无缘无故挂掉,还有位客户抱怨 VPS经常死机,登陆到终端看了一下,都是常见的 Out of memory问题。这通常是因为某时刻应用程序大量请求内存导致系统内存不足造成的,这通常会触发 Linux内核里的 Out of Memory(OOM) killer,OOM killer会杀掉某个进程以腾出内存留给系统用,不致于让系统立刻崩溃。如果检查相关的日志文件(/var/log/messages)就会看到下面类似的 Out of memory: Kill process信息:
...
Out of memory: Kill process 9682(mysqld) score 9 or sacrifice child
Killed process 9682, UID 27,(mysqld) total-vm:47388kB, anon-rss:3744kB, file-rss:80kB
httpd invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
httpd cpuset=/ mems_allowed=0
Pid: 8911, comm: httpd Not tainted 2.6.32-279.1.1.el6.i686#1
...
21556 total pagecache pages
21049 pages in swap cache
Swap cache stats: add 12819103, delete 12798054, find 3188096/4634617
Free swap= 0kB
Total swap= 524280kB
131071 pages RAM
0 pages HighMem
3673 pages reserved
67960 pages shared
124940 pages non-shared
Linux内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没有实际全部使用,为了提高性能,这部分没用的内存可以留作它用,这部分内存是属于每个进程的,内核直接回收利用的话比较麻烦,所以内核采用一种过度分配内存(over-commit memory)的办法来间接利用这部分“空闲”的内存,提高整体内存的使用效率。一般来说这样做没有问题,但当大多数应用程序都消耗完自己的内存的时候麻烦就来了,因为这些应用程序的内存需求加起来超出了物理内存(包括 swap)的容量,内核(OOM killer)必须杀掉一些进程才能腾出空间保障系统正常运行。用银行的例子来讲可能更容易懂一些,部分人取钱的时候银行不怕,银行有足够的存款应付,当全国人民(或者绝大多数)都取钱而且每个人都想把自己钱取完的时候银行的麻烦就来了,银行实际上是没有这么多钱给大家取的。
内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码 linux/mm/oom_kill.c,当系统内存不足的时候,out_of_memory()被触发,然后调用 select_bad_process()选择一个“bad”进程杀掉,如何判断和选择一个“bad”进程呢,总不能随机选吧?挑选的过程由 oom_badness()决定,挑选的算法和想法都很简单很朴实:最 bad的那个进程就是那个最占用内存的进程。
/**
* oom_badness- heuristic function to determine which candidate task to kill
*@p: task struct of which task we should calculate
*@totalpages: total present RAM allowed for page allocation
*
* The heuristic for determining which task to kill is made to be as simple and
* predictable as possible. The goal is to return the highest value for the
* task consuming the most memory to avoid subsequent oom failures.
*/
unsigned long oom_badness(struct task_struct*p, struct mem_cgroup*memcg,
const nodemask_t*nodemask, unsigned long totalpages)
{
long points;
long adj;
if(oom_unkillable_task(p, memcg, nodemask))
return 0;
p= find_lock_task_mm(p);
if(!p)
return 0;
adj=(long)p-signal-oom_score_adj;
if(adj== OOM_SCORE_ADJ_MIN){
task_unlock(p);
return 0;
}
/*
* The baseline for the badness score is the proportion of RAM that each
* task's rss, pagetable and swap space use.
*/
points= get_mm_rss(p-mm)+ p-mm-nr_ptes+
get_mm_counter(p-mm, MM_SWAPENTS);
task_unlock(p);
/*
* Root processes get 3% bonus, just like the __vm_enough_memory()
* implementation used by LSMs.
*/
if(has_capability_noaudit(p, CAP_SYS_ADMIN))
adj-= 30;
/* Normalize to oom_score_adj units*/
adj*= totalpages/ 1000;
points+= adj;
/*
* Never return 0 for an eligible task regardless of the root bonus and
* oom_score_adj(oom_score_adj can't be OOM_SCORE_ADJ_MIN here).
*/
return points 0? points: 1;
}
上面代码里的注释写的很明白,理解了这个算法我们就理解了为啥 MySQL躺着也能中枪了,因为它的体积总是最大(一般来说它在系统上占用内存最多),所以如果 Out of Memeory(OOM)的话总是不幸第一个被 kill掉。解决这个问题最简单的办法就是增加内存,或者想办法优化 MySQL使其占用更少的内存,除了优化 MySQL外还可以优化系统(优化 Debian 5,优化 CentOS 5.x),让系统尽可能使用少的内存以便应用程序(如 MySQL)能使用更多的内存,还有一个临时的办法就是调整内核参数,让 MySQL进程不容易被 OOM killer发现。
我们可以通过一些内核参数来调整 OOM killer的行为,避免系统在那里不停的杀进程。比如我们可以在触发 OOM后立刻触发 kernel panic,kernel panic 10秒后自动重启系统。
# sysctl-w vm.panic_on_oom=1
vm.panic_on_oom= 1
# sysctl-w kernel.panic=10
kernel.panic= 10
# echo"vm.panic_on_oom=1"/etc/sysctl.conf
# echo"kernel.panic=10"/etc/sysctl.conf
从上面的 oom_kill.c代码里可以看到 oom_badness()给每个进程打分,根据 points的高低来决定杀哪个进程,这个 points可以根据 adj调节,root权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3%的优惠(adj-= 30;分数越低越不容易被杀掉)。我们可以在用户空间通过操作每个进程的 oom_adj内核参数来决定哪些进程不这么容易被 OOM killer选中杀掉。比如,如果不想 MySQL进程被轻易杀掉的话可以找到 MySQL运行的进程号后,调整 oom_score_adj为-15(注意 points越小越不容易被杀):
# ps aux| grep mysqld
mysql 2196 1.6 2.1 623800 44876? Ssl 09:42 0:00/usr/sbin/mysqld
# cat/proc/2196/oom_score_adj
0
# echo-15/proc/2196/oom_score_adj
当然,如果需要的话可以完全关闭 OOM killer(不推荐用在生产环境):
# sysctl-w vm.overcommit_memory=2
# echo"vm.overcommit_memory=2"/etc/sysctl.conf
我们知道了在用户空间可以通过操作每个进程的 oom_adj内核参数来调整进程的分数,这个分数也可以通过 oom_score这个内核参数看到,比如查看进程号为981的 omm_score,这个分数被上面提到的 omm_score_adj参数调整后(-15),就变成了3:
# cat/proc/981/oom_score
18
# echo-15/proc/981/oom_score_adj
# cat/proc/981/oom_score
3
下面这个 bash脚本可用来打印当前系统上 oom_score分数最高(最容易被 OOM Killer杀掉)的进程:
# vi oomscore.sh
#!/bin/bash
for proc in$(find/proc-maxdepth 1-regex'/proc/[0-9]+'); do
printf"%2d%5d%sn"
"$(cat$proc/oom_score)"
"$(basename$proc)"
"$(cat$proc/cmdline| tr''''| head-c 50)"
done 2/dev/null| sort-nr| head-n 10
# chmod+x oomscore.sh
#./oomscore.sh
18 981/usr/sbin/mysqld
4 31359-bash
4 31056-bash
1 31358 sshd: root@pts/6
1 31244 sshd: vpsee [priv]
1 31159-bash
1 31158 sudo-i
1 31055 sshd: root@pts/3
1 30912 sshd: vpsee [priv]
1 29547/usr/sbin/sshd-D
总结遇到的几次MongoDB副本集初始化失败问题
前言:
在之前搭建MongoDB集群中,遇到过几次小问题引起的初始化副本集失败,都是之前初学时踩的坑,做个小结。
1、IP错误引起MongoDB副本集初始化失败
这个错误在另一篇文章已经描述过,这里略过不赘述。
详情见博客:IP错误引起MongoDB副本集初始化失败
2、PRIMARY与SECONDARY主机mongodb-keyfile文件内容不一致,导致在PRIMARY上添加副本集失败
问题描述:
搭建另外一个MongoDB副本集,主机和角色分配如下:
主机IP
角色
系统
131.10.11.106
PRIMARY
centos7
131.10.11.111
SECONDARY
centos7
131.10.11.114
SECONDARY
centos7
MongoDB server version: 3.4.10.1
在PRIMARY上添加SECONDARY主机131.10.11.111,出现下面的报错:
mongotest:PRIMARY> rs.add("131.10.11.111:27017")
{
"ok": 0,
"errmsg":"Quorum check failed because not enough voting nodes responded; required 2 but only the following 1 voting nodes responded: 131.10.11.106:27017; the following nodes did not respond affirmatively: 131.10.11.111:27017 failed with Authentication failed.",
"code": 74,
"codeName":"NodeNotFound"
}
原因分析:
经过排查,发现131.10.11.111主机的mongodb-keyfile和主节点不一致,并且在131.10.11.111主机的配置文件mongo.conf文件没有配置安全认证,所以导致了初始化失败
解决方法:
1、将PRIMARY节点上的mongodb-keyfile文件复制到备节点131.10.11.111上,并且修改权限为400
2、并且修改配置文件/etc/mongodb/mongo.conf如下:
[root@mongodb111 mongodb]# cat mongo.conf
systemLog:
destination: file
path:"/opt/mongodbdata/mongod.log"
logAppend: true
storage:
journal:
enabled: true
dbPath:/opt/mongodbdata
setParameter:
enableLocalhostAuthBypass: true
processManagement:
fork: true
pidFilePath:"/opt/mongodbdata/mongod.pid"
replication:
replSetName: mongotest
#添加下面几行:
security:
authorization: enabled
keyFile:"/etc/mongodb/mongodb-keyfile"
[root@mongodb111 mongodb]#
重启131.10.11.111机器mongodb,然后重新在PRIMARY上执行 rs.add("131.10.11.111:27017"),成功。
3、备节点配置文件没有配置replSet,导致添加副本集失败
问题描述:
这个问题和问题2是在同一个环境中遇到的,在106主机上添加114主机的时候,报下面的错误:
mongotest:PRIMARY> rs.add("131.10.11.114:27017")
{
"ok": 0,
"errmsg":"Quorum check failed because not enough voting nodes responded; required 2 but only the following 1 voting nodes responded: 131.10.11.106:27017; the following nodes did not respond affirmatively: 131.10.11.114:27017 failed with not running with--replSet",
"code": 74,
"codeName":"NodeNotFound"
}
原因分析:
根据提示“the following nodes did not respond affirmatively: 131.10.11.114:27017 failed with not running with--replSe”,查看了114主机的配置文件mongo.conf,发现这是因为备节点上的配置文件里面没有配置副本集,所以无法添加
解决方法:
修改备节点的/etc/mongodb/mongo.conf配置文件如下,加上副本集配置:
[root@mongodb114 mongodb]# cat mongo.conf
systemLog:
destination: file
path:"/opt/mongodbdata/mongod.log"
logAppend: true
storage:
journal:
enabled: true
dbPath:/opt/mongodbdata
setParameter:
enableLocalhostAuthBypass: true
processManagement:
fork: true
pidFilePath:"/opt/mongodbdata/mongod.pid"
security:
authorization: enabled
keyFile:"/etc/mongodb/mongodb-keyfile"
replication:#加上副本集配置,
replSetName: mongotest#name要注意和主节点上保持一致
[root@mongodb114 mongodb]#
重启131.10.11.114机器mongodb,然后重新在PRIMARY上执行 rs.add("131.10.11.114:27017"),成功
4、bindIp默认127.0.0.1,导致MongoDB副本集初始化失败
问题描述:
有一次搭建一个MongoDB副本集,主机和角色分配如下:
主机IP
角色
系统
10.0.0.101
PRIMARY
centos7
10.0.0.102
SECONDARY
centos7
10.0.0.103
SECONDARY
centos7
MongoDB server version: 4.0.2
在PRIMARY主机10.0.0.101上加入SECONDARY主机10.0.0.102的时候出现这个错误:
添加从节点失败:
CrystalTest:PRIMARY> rs.add("10.0.0.102:27017")
{
"operationTime": Timestamp(1539054715, 1),
"ok": 0,
"errmsg":"Quorum check failed because not enough voting nodes responded; required 2 but only the following 1 voting nodes responded: 10.0.0.101:27017; the following nodes did not respond affirmatively: 10.0.0.102:27017 failed with Error connecting to 10.0.0.102:27017:: caused by:: Connection refused",
"code": 74,
"codeName":"NodeNotFound",
"$clusterTime":{
"clusterTime": Timestamp(1539054715, 1),
"signature":{
"hash": BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId": NumberLong(0)
}
}
}
原因分析:
看到“failed with Error connecting to 10.0.0.102:27017:: caused by:: Connection refused”的时候很疑惑,因为10.0.0.102主机上的27017端口是OK的,服务也能正常使用,防火墙什么的都是关掉了的,尝试在PRIMARY主机10.0.0.101主机上telnet,发现不通:
[root@test101~]# telnet 10.0.0.102 27017
Trying 10.0.0.102...
telnet: connect to address 10.0.0.102: Connection refused
然后到102主机上查看端口,发现bindIp是127.0.0.1,问题应该就是这里了。bindIp是127.0.0.1,因此导致了10.0.0.101主机连不过去:
[root@test102~]# netstat-tlunp|grep mongo
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 1065/mongod#显示的是127.0.0.1:27017
解决方法:
修改102主机的mongo.conf加入“bindIp: 0.0.0.0”,然后重启102主机的MongoDB
[root@test102 bin]# cat/etc/mongodb/mongo.conf
systemLog:
destination: file
path:"/opt/mongodbdata/mongod.log"
logAppend: true
storage:
journal:
enabled: true
dbPath:/opt/mongodbdata
setParameter:
enableLocalhostAuthBypass: true
processManagement:
fork: true
pidFilePath:"/opt/mongodbdata/mongod.pid"
replication:
replSetName: CrystalTest
security:
authorization: enabled
keyFile:"/etc/mongodb/mongodb-keyfile"
net:
port: 27017
bindIp: 0.0.0.0#加入这一行
再查看端口:
[root@test102 mongodb]# netstat-tlunp|grep 27017
tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 3433/mongod#变成了0 0.0.0.0:27017
[root@test102 mongodb]#
然后在101主机上telnet,可以连过去了:
[root@test101~]# telnet 10.0.0.102 27017
Trying 10.0.0.102...
Connected to 10.0.0.102.
Escape character is‘^]‘.
^C^C
Connection closed by foreign host.
[root@test101~]#
重新在PRIMARY主机10.0.0.101添加102主机,就成功了:
CrystalTest:PRIMARY> rs.add("10.0.0.102:27017")
{
"ok": 1,
"operationTime": Timestamp(1539056959, 1),
"$clusterTime":{
"clusterTime": Timestamp(1539056959, 1),
"signature":{
"hash": BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId": NumberLong(0)
}
}
}总结遇到的几次MongoDB副本集初始化失败问题
标签:headcentosnectelnetnodalt修改mongodtry