“-bash: fork: 无法分配内存”

/ Linux / 没有评论 / 86浏览

当你输入任何shell命令都会见到报这个错的时候你就知道粗大事了。 此时多次敲命令,运气好的话还是能执行一些简单命令的。

问题定位

  1. 内存用完了? 首先肯定是看看内存占用
free -h

嗯,内存还有很多富余

  1. pid达到最大值?
sysctl kernel.pid_max  #查看最大进程数
ps -eLf | wc -l        #查看进程数
修改最大进程数后系统恢复
echo 1000000 > /proc/sys/kernel/pid_max
永久生效
echo "kernel.pid_max=1000000 " >> /etc/sysctl.conf
sysctl -p
  1. 据说还有overcommit_memory导致的情况

/proc/sys/vm/overcommit_memory参数说明: 取值为0,系统在为应用进程分配虚拟地址空间时,会判断当前申请的虚拟地址空间大小是否超过剩余内存大小,如果超过,则虚拟地址空间分配失败。因此,也就是如果进程本身占用的虚拟地址空间比较大或者剩余内存比较小时,fork、malloc等调用可能会失败。 取值为1,系统在为应用进程分配虚拟地址空间时,完全不进行限制,这种情况下,避免了fork可能产生的失败,但由于malloc是先分配虚拟地址空间,而后通过异常陷入内核分配真正的物理内存,在内存不足的情况下,这相当于完全屏蔽了应用进程对系统内存状态的感知,即malloc总是能成功,一旦内存不足,会引起系统OOM杀进程,应用程序对于这种后果是无法预测的 取值为2,则是根据系统内存状态确定了虚拟地址空间的上限,由于很多情况下,进程的虚拟地址空间占用远大小其实际占用的物理内存,这样一旦内存使用量上去以后,对于一些动态产生的进程(需要复制父进程地址空间)则很容易创建失败,如果业务过程没有过多的这种动态申请内存或者创建子进程,则影响不大,否则会产生比较大的影响

关于overcommit_memory 这个参数,参考link

ps:linux进程、线程

理解Linux的进程,线程,PID,LWP,TID,TGID

watcher.sh

    while true; do
     pid_max=`sysctl  kernel.pid_max | awk '{print $3}'`
     pid_now=`ps -eLf | wc -l`
     the_engine=`ps -ef | grep Application | grep -v grep | awk '{print $2}'`
     pid_engine=`ps hH p ${the_engine}| wc -l`
     the_emqx=`ps -ef | grep emqx | grep -v grep | awk '{print $2}'`
     pid_emqx=`ps hH p ${the_emqx}| wc -l`
     echo 'pid_max='${pid_max}' pid_now='${pid_now}' pid_engine='${pid_engine}' pid_emqx='${pid_emqx}
     sleep 1
     done