服务器, 运营维护

Linux下简单实现单用户资源限制思路

Linux是一个多用户&任务系统。如何防止某些用户占用服务器大量资源,避免影响其他用户的正常使用,是一个永不过时的话题。

很多人采用了国外的Cloudlinux,不过几十元一个月的授权费对于我这样一个学生来说,压力有点大。

前几个星期,我的某个服务器上某个用户被CC了,该用户的HTTPD进程占用了服务器大量资源,最后只能硬重启解决。

从那天开始,如何免费实现限制单用户的资源成为了我的一个迫不及待要解决的问题。

一:获取用户进程以及资源使用信息

Linux下能查看各用户的进程以及资源占用情况的命令有ps和top。其中top是交互式的,不太适合文本处理,因此要选用ps。

ps常用的参数有以下:

要获取各各用户的进程数,所占用的CPU与内存,就要用到参数a,u,x了。

执行

可以看到输出了类似下面的信息:

让我们来分析一下上面的数据。

第一列:此进程的用户

第二列:此进程的PID

第三列:此进程的CPU使用率

第四列:此进程的物理内存使用率

第五列:虚拟内存使用量

其余的没多大关系,我也不介绍了。

可以利用该命令与参数所输出的内容进行处理,格式化输出。例如内存使用率(量)总和,该用户的进程数目,其中可能使用到的有awk,print,cut,uniq和sort,从而实现获取某个用户的进程数,CPU使用率,内存使用率(量),再与自己所设置的值进行对比。

 

二:结束超资源用户的进程

当用户的资源超过设定值怎么办呢?由于我不是像CloudLinux那样的改动内核,因此也无法实现禁止某个用户继续fork进程。唯一的办法就是结束掉该用户的所有进程。那么就出现非常关键的一步:排除root,还有其他相关的守护进程的master进程。可以在前面获取用户进程的步骤使用grep或者egrep的v参数进行排除。

结束掉一个用户的所有进程,最佳的命令是killall了,其中的-u参数可以指定用户名。另外,killall结束进程时也可以指定对进程发出的信号,常用的有以下数个:

号码 名称 内容
1 SIGHUP 让该进程重新读取配置文件。
2 SIGINT 退出,相当于按Ctrl+[c]
9 SIGKILL 强制结束进程。
15 SIGTERM 以正常方式结束该进程。
19 SIGSTOP 暂停该进程,相当于Ctrl+[z]

与结束相关的有15和9,不指定信号的情况下,killall默认对进程发出信号15,这信号是正常退出进程,也就是让该进程完成任务再退出。明显不允许这样,因此我建议使用信号9。

FAQ:如果该用户的apache进程超了,被killall结束掉,会不会影响其余用户的正常使用?

答案是否定的,只要master进程还在,该用户和其他用户的apache进程还会被创建。也就是apache仍然能提供正常服务。

例子:

三:步骤一与二结合

最后的问题就是,把上面的一与二结合起来。可以考虑使用for循环:

把步骤二所获取到的用户信息赋值到一个变量,一个用户一行,使用for循环就能实现逐个用户处理。

四:循环

可能有人会想到cron,这东西频率太低了。循环执行该Shell Script,可以制造一个“死循环”,while命令即可:

上面使用了sleep进行延时,作用就是降低一个循环的间隔,如果不延时,可能会使该Shell Script所占用的CPU异常高。

可能有人会担心,第一步,也就是获取信息的那一步,用户量大时,数据的处理要花太多时间,不过经过我的测试,只要内存使用率(量)求和的方法正确,所花的时间基本能忽略。

由于被某论坛的人恶心了,因此我就不打算把成品发出来了,各位根据此文章的思路,自行开发吧。

Comments are closed.