CentOS下PHP exec()启动的后台进程持续重复创建问题求助
问题排查:CentOS下PHP exec()启动后台脚本重复创建进程的原因与修复
问题背景
你提到在EasyApache3+PHP5.4环境下正常运行多年的脚本,升级到EasyApache4+PHP5.6后,通过exec()启动的后台脚本会持续重复创建进程,最终耗尽服务器资源,还出现PHP Warning: exec(): Unable to fork的错误。
涉及代码
PHP 01(前端触发脚本)
<html> <body> Test <? echo "Date: " . date("d/m/Y h:i:sa");?> - run PHP exec () that call a second script in background.php script.<br><br> The script create a txt file.<br><br><br><br> <a href="http://domain/index.php" class="login_admin">Return to homepage....</a> </body> </html> <?PHP error_reporting(E_ALL); echo "<script language=\"javascript\"> window.alert('The create txt file process will be started in background.'); </script>"; exec("php -f /full_path/a_teste_exec_03_background.php > /full_path/a_teste_03.txt &", $o, $v); print_r($o); echo $v; ?>
PHP 02(后台执行脚本)
<?PHP $a_teste_log = fopen("a_teste_03_log.txt","a"); $linha_log = "\n\r" . date("Y-m-d h:i:sa") . " - Creation file...\n\r"; fwrite($a_teste_log, $linha_log); fclose($a_teste_log); exit; ?>
问题原因分析
结合EasyApache4(EA4)和PHP5.6的环境特性,主要问题集中在以下几点:
- PHP CLI路径未明确指定:EA4是多版本PHP共存环境,默认的
php命令可能不再指向CLI版本,而是FastCGI或其他SAPI入口。此时调用php -f ...启动的不是CLI进程,而是处理HTTP请求的进程,这类进程无法正常后台运行,甚至会因环境异常重复触发新进程。 - 后台进程未正确脱离终端:原命令仅重定向了标准输出,未处理标准错误,也没有用
nohup脱离终端。当父Web进程结束后,子进程可能因终端关联问题无法正常退出,甚至被系统异常重启。 - EA4的PHP运行模式变化:EA3默认用mod_php(Apache模块),EA4通常采用PHP-FPM模式。PHP-FPM的运行用户、环境变量与mod_php不同,可能导致
exec()调用的命令权限或环境异常,引发进程异常。
修复方案
1. 明确指定PHP CLI的完整路径
先在SSH终端找到PHP5.6 CLI的实际路径:
which php56-cli # 或用cpanel命令查看当前PHP版本路径 /usr/local/cpanel/bin/rebuild_phpconf --current
通常路径类似/usr/local/php56/bin/php,然后修改exec()中的命令,替换php为完整路径。
2. 完善后台命令的执行参数
使用nohup让进程脱离终端,同时重定向标准错误到标准输出,避免因输出缓冲区问题导致进程挂起:
exec("nohup /usr/local/php56/bin/php -f /full_path/a_teste_exec_03_background.php > /full_path/a_teste_03.txt 2>&1 &", $o, $v);
说明:
2>&1表示将stderr(错误输出)重定向到stdout(标准输出),确保所有输出都写入日志文件;nohup会让进程忽略终端挂断信号,即使Web进程结束,后台脚本也能正常执行并退出。
3. 检查PHP配置限制
- 确认
php.ini中disable_functions未包含exec; - 检查
open_basedir配置,确保/full_path/目录在允许的访问范围内; - 验证PHP-FPM运行用户对
/full_path/目录有读写权限。
4. 手动测试命令
先在SSH终端手动执行修改后的命令,验证是否正常生成日志,且进程执行后自动退出:
nohup /usr/local/php56/bin/php -f /full_path/a_teste_exec_03_background.php > /full_path/a_teste_03.txt 2>&1 & # 查看进程状态 ps aux | grep a_teste_exec_03_background.php # 等待几秒后再次查看,确认进程已退出
内容的提问来源于stack exchange,提问作者Ronaldo Luiz
相关产品推荐
相关产品推荐

