天天看点

php中的system方法偶尔会出现unable to fork

背景

php代码中调用了system方法,执行了shell脚本,一开始运行正常,过一段时间偶尔会出现unable to fork的报错

问题原因

system调用会fork新的进程,因为每个用户有最大进程数限制,简单的说就是达到用户的进程上限了

如何限制linux用户的进程数

这个可以通过修改如下文件来设定:

vi /etc/security/limits.conf

vpsee hard nproc 32

@student hard nproc 32

@faculty hard nproc 64

限制vpsee这个用户只能 fork 32 个进程

限制 student 这个用户组的每个成员最多能fork 32 个进程

限制 faculty 这个用户组的每个成员最多能 fork 64 个进程。

不过要事先检查系统是否有pam_limits.so 这个模块以及是否已经加载:

ls /lib64/security/pam_limits.so

/lib64/security/pam_limits.so

vi /etc/pam.d/login

session required pam_loginuid.so

如果自己是 Linux 普通用户,不是 root 用户不能修改 limits.conf 和重启系统的话,可以用 ulimit来临时限制自己允许创建的进程数,ulimit 有 Hard 和 Soft 两种方法限制

用 Hard的话可以减少最大可用的进程数,但是就不能重新增大这个限制了;用 Soft 的话可以自己自由增大和减小限制(ulimit,-H 和 -S的详细说明可以参看 man ulimit)。

不同的 Linux 版本对这个 ulimit -u 的默认值不同,在 CentOS上默认情况下最大运行进程数是 8256,在 Fedora 上是1024,不过改成32后就不能再改成比32更大的了(比如64),只能再改成比32小的

ulimit 不带 -H 和 -S 参数的时候同时设置 Hard 和 Soft:

ulimit -u

65535

ulimit -u 65534

ulimit -u 65535

-bash: ulimit: max user processes: cannot modify limit: Operation not permitted

ulimit -a

core file size          (blocks, -c) 0

data seg size           (kbytes, -d) unlimited

scheduling priority             (-e) 0

file size               (blocks, -f) unlimited

pending signals                 (-i) 30493

max locked memory       (kbytes, -l) 64

max memory size         (kbytes, -m) unlimited

open files                      (-n) 65535

pipe size            (512 bytes, -p) 8

POSIX message queues     (bytes, -q) 819200

real-time priority              (-r) 0

stack size              (kbytes, -s) 10240

cpu time               (seconds, -t) unlimited

max user processes              (-u) 65534

virtual memory          (kbytes, -v) unlimited

file locks                      (-x) unlimited

查看各系统用户的进程数(LWP)

默认情况下采用 ps 命令并不能显示出所有的进程。因为 Linux 环境下执行多线程,每个线程都将以一个轻量级进程(light-weight process [LWP])的形式执行,而 ps 命令如果不带 -L 选项将无法查看 LWP。

查看各系统用户的进程数的命令如下所示,执行后可得类似如下结果。

ps h -Led -o user | sort | uniq -c | sort -n

      2 nobody

      3 redis

     34 www

     64 mysql

    174 root

如果某个用户的 nproc 的软限制小于其运行中的进程数,则切换用户时将报错 "su: cannot set user id: Resource temporarily unavailable"

参数详解:

h  :   No header. (or, one header per screen in the BSD personality) ,The h option is problematic. Standard BSD ps uses this option to print a header on each page of output, but older Linux ps uses this option to totally disable the header. This version of ps follows the Linux usage of not printing the header unless the BSD personality has been selected, in which case it prints a header on each page of output. Regardless of the current personality,you can use the long options --headers and --no-headers to enable printing headers each page or disable headers entirely, respectively.

译:简单说就是不输出header,但是Standard BSD 会用它展示header,最好用  --no-headers 参数更明确

-L  :Show threads, possibly with LWP and NLWP columns

译:展示轻量级进程

-e :  Select all processes.  Identical to -A

-d :  Select all processes except session leaders.

什么是session leader。参考该解释:​​http://www.win.tue.nl/~aeb/linux/lk/lk-10.html#ss10.3​​

-o : user-defined format

译:只输出哪些列  user:所属用户  nlwp:轻量级进程数量 lwp: 轻量级进程ID   args:命令

确定某用户的进程(LWP)数的分布情况

根据上面的命令可确定 nproc 参数接近上限的问题用户,随后应确定该用户进程数(LWP)的分布情况。

ps -o nlwp,pid,lwp,args -u username | sort -n

其中 username 为系统用户名,根据查询结果,便可轻易确定存在问题的程序。如果程序均正常,而 nproc 参数已接近上限值,则需修改 nproc 参数。

解决方法

继续阅读