nohup启动的10000个Asterisk测试进程为何突然全部终止?
问题分析与解决方案
咱们来拆解下你遇到的这个问题——10000个pjsua进程刚创建完成就集体被杀,哪怕用了nohup和disown,这大概率不是nohup失效,而是系统层面的资源限制或进程管理机制在起作用,我给你一步步梳理:
先明确你的场景
你通过PHP的exec()调用Linux命令,批量创建Asterisk电话账号做压力测试,核心命令如下:
nohup /usr/src/pjproject-2.3/pjsip-apps/bin/pjsua-x86_64-unknown-linux-gnu --id=sip:%s@13.113.163.3 --registrar=sip:127.0.0.1:25060 --realm=* --username=%s --password=123456 --local-port=%s --null-audio --no-vad --max-calls=32 --no-tcp >>/dev/null 2>>/dev/null & $(echo -ne '\r')
之前尝试用screen但因创建10000个screen导致CPU过载服务器崩溃,改用nohup+disown后,进程全部被杀。
可能的核心原因
1. 系统进程数上限触发
Linux对每个用户、全局的进程数量都有默认限制,一次性创建10000个进程很可能突破了这个阈值:
- 用
ulimit -u查看当前用户的最大进程数限制(默认一般是1024或4096) - 用
sysctl kernel.pid_max查看全局PID上限(默认一般是32768)
当达到上限后,系统会强制终止新进程,甚至清理已有进程来维持稳定。
2. 内存耗尽触发OOM Killer
每个pjsua进程哪怕启用了--null-audio,也会占用一定内存和系统资源。10000个进程叠加后,极可能把系统内存榨干,这时Linux的OOM(Out-of-Memory) Killer会自动查杀占用资源较多的进程组,你的所有pjsua进程属于同类高资源进程,就会被批量清理。
- 检查系统日志:
dmesg | grep -i oom或者查看/var/log/messages(不同发行版路径可能不同),如果出现Out of memory: Killed process ... (pjsua-x86_64-unkn)这类日志,就能实锤是这个原因。
3. PHP进程组的潜在影响
虽然你用了nohup忽略SIGHUP信号,也执行了disown,但如果PHP的父进程(比如Apache、PHP-FPM)在脚本执行完后退出,可能会意外影响到子进程组。另外你命令里的$(echo -ne '\r')是多余的,没必要在后台进程后加这个,反而可能干扰进程的后台运行状态。
4. Asterisk服务器的注册限制
可能性相对小,但可以排查下Asterisk的配置:如果Asterisk设置了最大注册账号数,当达到10000个后,可能会主动拒绝注册甚至发送信号导致pjsua进程退出。可以查看Asterisk日志/var/log/asterisk/messages确认。
针对性解决方案
1. 调整系统资源限制
- 临时调整用户进程数:执行
ulimit -u 20000(仅当前会话有效) - 永久生效:修改
/etc/security/limits.conf,添加:your_username soft nproc 20000 your_username hard nproc 20000 - 调整全局PID上限:临时执行
sysctl -w kernel.pid_max=65535,永久生效则修改/etc/sysctl.conf添加kernel.pid_max=65535,再执行sysctl -p加载配置。
2. 优化pjsua进程资源占用
- 精简pjsua参数:比如添加
--no-log关闭日志、固定RTP端口范围(--min-rtp-port/--max-rtp-port)减少资源消耗,或者降低--max-calls=32到实际需要的数值(如果压力测试不需要这么高的并发呼叫数)。 - 考虑用更轻量的SIP注册工具:比如
sipgrep或者自定义轻量SIP客户端,替代pjsua减少每个进程的内存占用。
3. 分批创建进程
不要一次性创建10000个进程,分批次创建并间隔休息,给系统足够的资源分配时间。修改PHP脚本的循环逻辑:
while ($min_accounts < $max_accounts) { $shell = new shell(); // ... 你的现有创建逻辑 ... $min_accounts++; // 每创建1000个进程休息5秒 if ($min_accounts % 1000 == 0) { sleep(5); } }
4. 简化命令冗余部分
去掉命令里多余的$(echo -ne '\r'),简化为:
nohup /usr/src/pjproject-2.3/pjsip-apps/bin/pjsua-x86_64-unknown-linux-gnu --id=sip:%s@13.113.163.3 --registrar=sip:127.0.0.1:25060 --realm=* --username=%s --password=123456 --local-port=%s --null-audio --no-vad --max-calls=32 --no-tcp >>/dev/null 2>>/dev/null &
内容的提问来源于stack exchange,提问作者Wesley Schravendijk

