Chinaunix首页 | 论坛 | 博客
  • 博客访问: 474459
  • 博文数量: 51
  • 博客积分: 8010
  • 博客等级: 中将
  • 技术积分: 1235
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-12 10:47
文章分类

全部博文(51)

文章存档

2009年(13)

2008年(38)

我的朋友

分类:

2008-05-23 16:14:08

最近给学院弄的那个院网,真的把我囧死了,在本地调试很正常很安全的站,一上学校服务器就一大堆问题,而且都很隐蔽,服务器用的是IIS+PHP插件,版本很新,可惜真不明白它怎么配置的,老是跟我的网站过不去。

跟以往一样,由于服务器支持PHP+Mysql,所以选择了FleaPHP+Smarty的搭配,前台不用自己弄,所以什么jQuery呀Mootools呀就不用理了。

网站一传上去第一眼就让我傻了眼,全空白,无论前台后台都一样,一片白茫茫,开始以为是文件编码问题,但检查了一遍也找不到。于是上网问同行,被告 之FLEA这个目录如果传输不完整的话也有这个可能,觉得有道理,于是重传了一遍,依然不行。后来用phpinfo查了一下,才知道这网站关了 display_error的,后来逐行加echo(本地可以用ZDE调试,但远程就……),发现停在FLEA::runMVC,由于是在某人机子上调试 的,东西用起来很麻烦,就没继续下去。

当时觉得是因为服务器用了中文目录,导致的问题,但没有显错,什么都做不了。于是找技术中心那边的某老师改成英文目录名,下午一早下班就回来调试,却发现,依然有问题。

于是有自己的机器用ZDE连上去,依然是用echo法,发现停在预载入文件里,在载入Lib_Core时出错了,这是我写的一个核心库,一直用都没问题,再跟踪,发现问题出在这一句

/**
* 修正时差 当前时区为 中华人民共和国
*/

date_default_timezone_set('PRC');

服务器本身已经有时区设定了,但在一般来说这句都不会有问题,汗一个校服务器先。

搞定这个之后就能显示了,用Navicat上传了Mysql数据库后(汗,我最以为会出问题的地方,居然成功运行了),就做点小改动,把文件整理好,把权限设置好,本以为搞定了,想不到恶梦又来了。
因为前台有点改动,于是就动了一下TPL目录,这是我放Smarty和非Smarty模板的目录,更新了里面的文件后发现更新不能,自然就想到是编译目录的问题,删了一大堆tmp、php、ini文件后(注意了,有tmp),居然出问题了,再度白屏。
这次的白屏是所有涉及Smarty的地方,开始以为是Smarty的目录权限不够,一查发现全是0777,重传了一次Smarty Libs,问题依然,重传了一次整站,问题依然,于是好奇地把本地调试时弄的旧的TPL和TPL_C(编译目录)的文件覆盖回去,居然又能动了??!!
再对比一下本地的TPL_C和服务器上的TPL_C,可以发现本地的文件全是php和ini格式的编译文件,而服务器上的全是tmp,上Smarty的官网查了一下,终于找到答案:

Smarty的编译文件是先生成tmp格式的临时文件再重命名回php和ini格式的编译文件的,使用的文件是:
internals/core.write_file.php,
官网上谈到这种情况,都围绕着一个问题:目录权限,但明显的,我的全是0777,并不是权限问题。
其他的谈及的情况如禁了tempnam(),目录不完整等,通过Debug,发现也没有这类问题。
那只好自己找问题了。
参考链接:


服务器上只有tmp而没有php和ini,明显的,我上传到服务器上的程序,能生成tmp但不能被重命名为目标文件名,通过调试,发现问题果然出现在rename上。

既然rename不能,那就只有用其他折衷的方法,我的方法是,不生成临时文件,直接生成新文件。

修改的文件是internals/core.write_file.php
旧的代码是:

function smarty_core_write_file($params, &$smarty)
{
$_dirname = dirname($params['filename']);
 
if ($params['create_dirs']) {
$_params = array('dir' => $_dirname);
require_once(SMARTY_CORE_DIR . 'core.create_dir_structure.php');
smarty_core_create_dir_structure($_params, $smarty);
}
 
// write to tmp file, then rename it to avoid file locking race condition
$_tmp_file = tempnam($_dirname, 'wrt');
 
if (!($fd = @fopen($_tmp_file, 'wb'))) {
$_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('wrt');
if (!($fd = @fopen($_tmp_file, 'wb'))) {
$smarty->trigger_error("problem writing temporary file '$_tmp_file'");
return false;
}
}
 
fwrite($fd, $params['contents']);
fclose($fd);
 
if (DIRECTORY_SEPARATOR == '\\' || !@rename($_tmp_file, $params['filename'])) {
// On platforms and filesystems that cannot overwrite with rename()
// delete the file before renaming it -- because windows always suffers
// this, it is short-circuited to avoid the initial rename() attempt
@unlink($params['filename']);
@rename($_tmp_file, $params['filename']);
}
@chmod($params['filename'], $smarty->_file_perms);
 
return true;
}

新修改成的代码为:

function smarty_core_write_file($params, &$smarty)
{
$_dirname = dirname($params['filename']);
 
if ($params['create_dirs']) {
$_params = array('dir' => $_dirname);
require_once(SMARTY_CORE_DIR . 'core.create_dir_structure.php');
smarty_core_create_dir_structure($_params, $smarty);
}
 
$fd = @fopen( $params['filename'], 'wb');
if(!$fd) return false;
fwrite($fd, $params['contents']);
fclose($fd);
@chmod($params['filename'], $smarty->_file_perms);
 
return true;
}

但如代码中注释所述,这个机制是为了解决文件死锁如写冲突一类的问题的,所以这种处理方法会有一定的可能出错,但学院网站的TPL不多,也不常改,这个可能可忽略不计,能用就好,折衷的处理也是无奈的事。

阅读(1821) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-12-09 21:49:35

你的这篇文章真的是救了我一命