我一直在使用以下方法编写网站:
- Zend Framework 1.11.5(完整 MVC)
- PHP 5.3.6
- Apache 2.2.19
- CentOS 5.6 i686 virtuozzo 在 vps 上
- cPanel WHM 11.30.1(版本 4)
- Mysql 5.1.56-日志
- Mysqli API 5.1.56
问题从这里开始https://stackoverflow.com/questions/6769515/php-programming-seg-fault。简而言之,php 给我带来了随机分段错误。
[Wed Jul 20 17:45:34 2011] [error] mod_fcgid: process /usr/local/cpanel/cgi-sys/php5(11562) exit(communication error), get unexpected signal 11
[Wed Jul 20 17:45:34 2011] [warn] [client 190.78.208.30] (104)Connection reset by peer: mod_fcgid: error reading data from FastCGI server
[Wed Jul 20 17:45:34 2011] [error] [client 190.78.208.30] Premature end of script headers: index.php
关于扩展。当我使用“--enable-debug”标志编译 php 时,我必须禁用此行:
zend_extension="/usr/local/IonCube/ioncube_loader_lin_5.3.so"
否则,服务器不会接受请求,我会收到“与服务器的连接已重置”的消息。出于同样的原因,我可能也必须禁用 eaccelerator。我仍然不明白为什么 apache 有时会运行它,而有时却不会:
extension="eaccelerator.so"
无论如何,在我运行 httpd 后,可能会随机出现段错误。如果我没有使用“--enable-debug”标志编译 php,我可能会确定地遇到 php 崩溃:
<?php
class Admin_DbController extends Controller_BaseController
{
public function updateSqlDefinitionsAction()
{
$db = Zend_Registry::get('db');
$row = $db->fetchRow("SHOW CREATE TABLE 222AFI");
}
}
?>
但是如果我使用“--enable-debug”标志编译 php,则很难出现此错误。我必须增加一些复杂性才能使其崩溃。我必须在几秒钟内执行许多并行请求才能崩溃:
<?php
class Admin_DbController extends Controller_BaseController
{
public function updateSqlDefinitionsAction()
{
$db = Zend_Registry::get('db');
$tableList = $db->listTables();
foreach ($tableList as $tableName){
$row = $db->fetchRow("SHOW CREATE TABLE " . $db->quoteIdentifier($tableName));
file_put_contents(
DB_DEFINITIONS_PATH . '/' . $tableName . '.sql',
$row['Create Table'] . ';'
);
}
}
}
?>
请注意,这是相同的脚本,但为数据库中的所有表而不是一个表创建 DDL。似乎如果 php 负载过重(带有扩展程序并且我执行了许多并行请求),php 就会崩溃。
关于使用“-X”启动 httpd:我试过了。问题是,使用 --enable-debug 很难让 php 崩溃。使用“-X”选项(仅启用一个子进程)我无法执行并行请求。所以我无法创建正确的调试回溯:https://bugs.php.net/bugs-generating-backtrace.php
我的具体问题是,我该怎么做才能获得核心转储?
root@GWT4 [~]# httpd -V
Server version: Apache/2.2.19 (Unix)
Server built: Jul 20 2011 19:18:58
Cpanel::Easy::Apache v3.4.2 rev9999
Server's Module Magic Number: 20051115:28
Server loaded: APR 1.4.5, APR-Util 1.3.12
Compiled using: APR 1.4.5, APR-Util 1.3.12
Architecture: 32-bit
Server MPM: Prefork
threaded: no
forked: yes (variable process count)
Server compiled with....
-D APACHE_MPM_DIR="server/mpm/prefork"
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=128
-D HTTPD_ROOT="/usr/local/apache"
-D SUEXEC_BIN="/usr/local/apache/bin/suexec"
-D DEFAULT_PIDLOG="logs/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_LOCKFILE="logs/accept.lock"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="conf/mime.types"
-D SERVER_CONFIG_FILE="conf/httpd.conf"
答案1
获取核心转储需要将rlimit
要获取核心转储的进程的“核心文件大小”设置为非零值。假设您在 FCGI 中运行 PHP,您实际上并不关心 Apache 本身,它不会出现分段错误;您需要运行一个脚本,ulimit -c unlimited
然后执行您的 FCGI 服务器。
我喜欢为核心设置一个单独的暂存分区,所以如果它们变得有点大或难以控制,它们不会在其他地方引起磁盘填充问题——设置/proc/sys/kernel/core_pattern
为类似的值/var/cores/%e-%p.core
。
答案2
您必须使用 ioncube_loader 和 eaccelerator 吗?至于 eaccelerator,它们对 5.3.x 的支持充其量也只是参差不齐,而且大多数 5.3 用户都依赖 APC(无论如何,通过 FCGI 也能更好地工作)。
如果您必须使用 eaccelerator,您是否会先执行“make distclean”,然后执行其常设的 INSTALL 指令(仔细检查您加载的 phpize 是否适用于 5.3.6,而不是以前安装的某些残留)?我怀疑这就是您的 coredump 的全部来源,而 Apache 根本不是罪魁祸首。
答案3
我找到了一个临时解决方案。虽然不太美观,但很合适:
公共函数 selectCmd($q){
$charsFrom = array("\\a", "\\t", "\\n", "\\v", "\\f", "\\r", "\\\\", "\\0", "\\\"", "\\\'", "\\b");
$charsTo = array("\a", "\t", "\n", "\v", "\f", "\r", "\\", "\0", "\"", "\'", "\b");
exec('echo ' . escapeshellarg($q) . ' | mysql' .
' -h ' . escapeshellarg($this->_config['host']).
' -u ' . escapeshellarg($this->_config['username']).
' -p' . escapeshellarg($this->_config['password']).
' ' . escapeshellarg($this->_config['dbname']), $output);
$colNames = explode("\t", array_shift($output));
foreach ($colNames as &$colName){
$colName = str_replace($charsFrom, $charsTo, $colName);
}
unset($colName);
$rowSet = array();
foreach ($output as $line){
$row = array();
$rawRow = explode("\t", $line);
for ($i = 0; $i < count($rawRow); ++ $i){
$row[$colNames[$i]] = str_replace($charsFrom, $charsTo, $rawRow[$i]);
}
$rowSet[] = $row;
}
return $rowSet;
}
您需要用真正的连接数组替换 $this->_config。
此脚本运行任何返回行的 SQL 命令。目前,这是我正在采取的解决方案。如果有人愿意主动帮助我,我仍然有源代码。我也是使用 PHPUnit 和 Zend(确定性)时遇到 PHP 段错误的人。我在工作中做这一切,没有资源来测试它。感谢您的理解。
答案4
不确定在这种情况下是否有帮助,但我只设置了一个子项,找到 PID,然后使用 strace 进行调试
strace -p PID