最新发表

mac升级到Yosemite导致goagent不能开机启动解决方案

今天把mac升级到Yosemite,结果发现goagent的进程不在了。采集者烂JJ

goagent的开机启动是使用mac的LaunchDaemons来实现的,在goagent的目录下有个addto-startup.py文件,执行这个脚本会在/Library/LaunchDaemons/目录下生成一个org.goagent.macos.plist文件,然后执行

http://leo108.com/pid-2021.asp

sudo launchctl load /Library/LaunchDaemons/org.goagent.macos.plist

就可以实现开机启动(实际上在执行完这条命令之后就会启动goagent进程)。但是现在进程却不存在了,通过命令mac升级到Yosemite导致goagent不能开机启动解决方案

sudo launchctl unload /Library/LaunchDaemons/org.goagent.macos.plist
sudo launchctl load /Library/LaunchDaemons/org.goagent.macos.plist

重新加载仍然不行。

goagent

于是查看mac官网对于LauchDaemons的文档,参照example试着自己写了个LauchDaemons,发现可以正常加载,于是判断是goagent的LauchDaemons有错误。

接下来就比较简单了,只要把org.goagent.macos.plist里面的配置逐个干掉,然后重新加载,看看干掉哪个配置的时候可以正常启动。

最终发现是WorkingDirectory这个配置导致,在我的配置里WorkingDirectory这个配置项是个空字符串,不知道是更新之后不支持了还是啥情况,总之干掉

<key>WorkingDirectory</key>
<string></string>

之后再加载goagent进程就出来了。

未经允许严禁转载

php原生模板引擎性能优化

好久没写博客了,今天来一发。

背景:

基于YAF开发的一个网站,模板引擎使用原生php,同时为了满足需求,自己开发了一个widget的功能,每次调用widget都会引发一次模板渲染。在网站首页会调用同一个widget数十次,在查看xhprof的数据时,发现widget渲染模板耗时较多,主要消耗在加载模板文件上,由于同一个widget使用的模板是同一个,所以希望只加载一次模板来提高执行效率。

采集者烂JJ

ab -n1000 -c50的结果是11.31qps(虚拟机性能差)yaf

思路:

首先想到的是在include文件之前把文件读入内存,放到一个静态变量中,之后再调用时就直接从静态变量中取即可。但问题是把模板文件放到变量中之后,怎么渲染呢?最简单粗暴的办法是使用eval,但是太粗暴了,不想使用。本文来自leo108's blog

然后想起来php有一个wrapper的功能,可以注册一个wrapper,比如mem,同样是把模板文件读入内存,然后就可以通过include(‘mem://模板引擎路径’)的方式来加载,大致代码如下:性能

class Ext_Wrapper {
    //存放模板文件内容的静态成员变量
    protected static $_fileArr = array();
    protected $_pos;
    protected $_curFile;

    public function stream_open($path, $mode, $options, &$opened_path) {
        $path = substr($path, 5, strlen($path) - 5);
        //判断模板文件是否已经在变量中,不存在就读取
        if (!isset(self::$_fileArr[$path])) {
            self::$_fileArr[$path] = file_get_contents($path);
        }
        $this->_curFile = $path;
        $this->_pos     = 0;
        return true;
    }
    public function stream_read($count) {
        //直接从静态变量中读数据
        $content = self::$_fileArr[$this->_curFile];
        $ret     = substr($content, $this->_pos, $count);
        $this->_pos += strlen($ret);
        return $ret;
    }
    //其他方法略
}
//注册wrapper
stream_register_wrapper('mem', 'Ext_Wrapper');

ab -n1000 -c50的结果是12.68qpsphp原生模板引擎性能优化

最后试了一下eval的性能,大致代码如下:

class Ext_View extends Yaf_View_Simple {
    private $tmpPath;
    private $tmpData = array();
    private $include;

    //用于保存模板内容的静态变量
    protected static $_fileArr = array();

    public function display($tplFile, $data = array()) {
        $this->tmpPath = $this->getScriptPath() . '/' . $tplFile;
        if (is_array($data)) {
            $this->tmpData = array_merge($this->tmpData, $data);
        }
        unset($tplFile);
        unset($data);
        extract($this->tmpData, EXTR_OVERWRITE);
        //判断模板文件是否已经在变量中,不存在就读取
        if (!isset(self::$_fileArr[$this->tmpPath])) {
            self::$_fileArr[$this->tmpPath] = file_get_contents($this->tmpPath);
        }
        eval('?>'.self::$_fileArr[$this->tmpPath]);
    }
    //其他代码略
}

ab -n1000 -c50的结果是15.07qps,吓尿了,eval果真是简单粗暴有效本文来自http://leo108.com

sonar中文乱码解决方案

OSC搞了一个代码质量管理系统,用的是sonar,看上去很不错,于是就自己搭建了一个,但是发现代码里的中文全部变了‘?’号。

首先检查代码,确认是UTF8格式无误。

再检查代码目录下的sonar-project.properties文件,编码配置sonar.sourceEncoding=UTF-8,也没有错。本文来自leo108's blog

然后检查数据库,发现数据库的字符集是latin,于是把所有的表字符集都改成utf8。

重新运行了一下sonar-run,以为能解决了,结果发现还是‘?’号。

检查数据库中的数据,已经是乱码的了,说明在写入的时候就有问题了。

再检查了一下sonar-run的配置,里面的jdbc配置是:

采集者烂JJ

sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&amp;characterEncoding=utf8

看上去是utf8没错啊……但是我发现里面有个&amp;,这个是&的转义,于是想会不会是这里的问题,把&amp;改成&,再运行sonar-run,显示中文正常!

piwik页面卡住问题追查记录

今天无聊就折腾了下piwik,但是发现有概率页面会504,查看nginx日志是php执行超时,而且第一次504之后,后面的所有页面访问全部都是504,重启php-fpm之后又可以正常访问了。未经允许严禁转载

于是打开php-fpm的slowlog,在页面504的时候slowlog里也打出了对应的调用栈:

script_filename = /home/www/online/website/piwik/index.php
[0x00007fbec1568f48] session_start() /home/www/online/website/piwik/libs/Zend/Session.php:469
[0x00007fbec1568370] start() /home/www/online/website/piwik/core/Session.php:113
[0x00007fbec1567e68] start() /home/www/online/website/piwik/core/FrontController.php:416
[0x00007fbec1567a08] prepareDispatch() /home/www/online/website/piwik/core/FrontController.php:502
[0x00007fbec15675f8] doDispatch() /home/www/online/website/piwik/core/FrontController.php:84
[0x00007fbec15671d0] dispatch() /home/www/online/website/piwik/core/dispatch.php:34
[0x00007fbec15669a0] +++ dump failed

看来是执行session_start的时候卡住了,php的session是有锁机制的,如果某个页面开启了session,并且该请求尚未结束,则后续该session的请求就会全部锁住,等待之前的请求结束。本文来自leo108's blog

也就是说piwki页面卡住的原因是之前的某次请求没有结束,但是是哪个请求没有结束呢?因为没有看piwik的代码,而且504是有概率出现的,并不是访问了某个特定的页面后才504,问题追到这里就遇到了瓶颈。

鼓捣了半天之后突然想到,那个没有结束的请求肯定会打在php的slowlog里面,于是重新检查了一下,果真在一堆session的slowlog中发现了不一样的日志:

script_filename = /home/www/online/website/piwik/index.php
[0x00007fbec1568c40] curl_exec() /home/www/online/website/piwik/core/Http.php:483
[0x00007fbec1568798] sendHttpRequestBy() /home/www/online/website/piwik/core/Http.php:94
[0x00007fbec15685e0] sendHttpRequest() /home/www/online/website/piwik/core/Http.php:720
[0x00007fbec1567e00] fetchRemoteFile() /home/www/online/website/piwik/plugins/ExampleRssWidget/RssRenderer.php:46
[0x00007fbec1567be8] get() /home/www/online/website/piwik/plugins/ExampleRssWidget/Controller.php:25
[0x00007fffe0d3cf00] rssPiwik() unknown:0
[0x00007fbec1567788] call_user_func_array() /home/www/online/website/piwik/core/FrontController.php:531
[0x00007fbec1567378] doDispatch() /home/www/online/website/piwik/core/FrontController.php:84
[0x00007fbec1566f50] dispatch() /home/www/online/website/piwik/core/dispatch.php:34
[0x00007fbec1566720] +++ dump failed

看上去是个curl调用http请求,追了下里面的代码,发现是个公共的类,并不是固定请求某个url,这也简单,在curl_exec()之前加个打日志的代码,把curl请求的url记录下来。http://leo108.com/pid-2007.asp

于是又随便点了记下piwik的页面,发现有记录了一个url:http://feeds.feedburner.com/Piwik未经允许严禁转载

看上去是rss的url,直接在piwik的grep这个url,结果如下:

./plugins/ExampleRssWidget/Controller.php:            $rss = new RssRenderer('http://feeds.feedburner.com/Piwik');
./plugins/ExampleRssWidget/Controller.php:            $rss = new RssRenderer('http://feeds.feedburner.com/PiwikReleases');

是个插件的代码。piwik

进到piwik的后台,直接把ExampleRssWidget这个插件禁用。问题解决!

http://leo108.com/pid-2007.asp

PS:中国的国情啊……………………

本文来自leo108's blog

json格式化、高亮库jsonFormater

JsonFormater

基于jQuery的json格式化、高亮库

核心代码参考天马行空工作室,本人只做了模块化和一些代码优化。

采集者烂JJ

demo

http://leo108.github.io/jsonFormater/

本文来自http://leo108.com

github地址

https://github.com/leo108/jsonFormater

jQuery

使用方式

引入jQuery

<script type="text/javascript" src="jquery-1.7.2.min.js"></script>

注意:jQuery版本要求>=1.7.2

http://leo108.com/pid-1996.asp

引入jsonFormater.js和jsonFormater.css

<script type="text/javascript" src="jsonFormater.js"></script>
<link href="jsonFormater.css" type="text/css" rel="stylesheet"/>

在html中新增一个空的元素作为显示的容器

例如<div id='container'></div>本文来自leo108's blog

调用JsonFormater

$(document).ready(function(){
    var options = {
        dom : '#container' //对应容器的css选择器
    };
    var jf = new JsonFormater(options); //创建对象
    jf.doFormat('{"string":"leo108"}'); //格式化json
});

效果图

效果图

JSON

详细使用方式

配置

支持的配置以及默认配置如下:

未经允许严禁转载

{
    dom: '',          //用于放置的dom的选择器
    singleTab: "  ",  //单个tab
    tabSize: 2,       //缩进数量
    quoteKeys: true,  //key是否用双引号包含
    imgCollapsed: "images/Collapsed.gif", //收起的图片路径
    imgExpanded: "images/Expanded.gif",  //展开的图片路径
    isCollapsible: true //是否支持展开收起
}

方法

var obj = new JsonFormater({dom: '#container'});
obj.doFormat(json) //格式化一个json字符串或者js对象
obj.expandAll()    //全部展开
obj.collapseAll()  //全部收起
obj.collapseLevel(level)  //展开到level层

 

JSON

WordPress语法高亮增强插件更新至2.5.0版本

WordPress语法高亮增强插件(SyntaxHighlighter++)今日更新至2.5.0版本,此版本是一个bug修复版本,主要是修复在高版本(>=3.7.0)的后台“多媒体”→“媒体库”中,点击编辑任意一个多媒体,多媒体页面会被本插件的输入框遮挡的问题。WordPress语法高亮增强插件更新至2.5.0版本

WordPress官方下载地址:http://wordpress.org/extend/plugins/syntax-highlighter-with-add-button-in-editor/

WordPress插件

单文件PHP开发框架SinglePHP1.0版发布

单文件PHP框架,羽量级网站开发首选。

http://leo108.com/pid-1986.asp

SinglePHP是一个单文件PHP框架,适用于简单系统的快速开发,提供了简单的路由方式,抛弃了坑爹的PHP模板,采用原生PHP语法来渲染页面,同时提供了widget功能,简单且实用。单文件PHP开发框架SinglePHP1.0版发布

协议MIT

github地址:https://github.com/leo108/SinglePHP

本文来自http://leo108.com

文档地址:http://leo108.github.io/SinglePHP/SinglePHP

以前在开发一些极其简单的项目时就比较纠结,不用框架吧代码结构比较乱,还要花时间去写那些数据库连接代码;用框架吧框架代码比业务代码还多,太臃肿了。http://leo108.com/pid-1986.asp

所以就想自己搞一个简单的框架,满足简单的网站开发需求即可,在开发的过程中也一直坚持简单的原则,可要可不要的功能一律砍掉。

本文来自leo108's blog

很久之前就开始酝酿这个项目,13年初的时候有了雏形,经过一年多的修修改改,也在几个小网站试验过,感觉差不多了,就在这两天把文档和注释完善了一下,今晚算是正式发布了。

本文来自http://leo108.com

IE JS下一个奇怪的特(bu)性(g)

前一阵子统计一个站点的nginx访问日志时发现了大量的404请求,这些请求的url比较奇怪,都是以/undefined/img/开头的图片文件,这些请求还有一个共同点,那就是ua全部都是ie。本文来自http://leo108.com

首先find一下图片的文件名,发现都是系统中用到的图片,是第三方登录的图片按钮,用不同浏览器去访问,发现只有确实只有较低版本(<=ie8)的ie浏览器会出现红叉叉。

搜索了下相关的代码,发现这些图片的url是用js拼接出来的,大概代码如下:

http://leo108.com/pid-1982.asp

var static_file_url = window.static_file_url;
html = '<img src="' + static_file_url + '/img/icon_bdshare_weibo.png" width="28" height="28" />';

而window.static_file_url是在页面头部就赋值了的,也就是说,当拼接url的时候,static_file_url并不是window.static_file_url的值,而是未定义undefined,在ie中alert这个变量,确实是undefined。采集者烂JJ

同时我发现了另一个奇怪的现象,在同一个js文件中有ajax请求,url也是拼接出来的,大概样子如下:

js

var ajax_url = window.server_url;
$.post(ajax_url, param, function(data){}, 'json');

而在这里的ajax请求却是正常的,alert(ajax_url)出来的值也是window.server_url的值。

本文来自http://leo108.com

这两个例子唯一的区别就是变量名,前者选择的变量名和window对象下的属性一致,而后者不一致,所以怀疑是这个地方的问题,于是写了一段测试代码

本文来自http://leo108.com

window.test_a = 'a';
window.test_b = 'b';
var test_a = window.test_a;
var test_b2 = window.test_b;
alert(test_a); // undefined
alert(test_b2); // b

所以在ie下的这个特(bu)性(g)真是让人爱(i)不(e)释(qu)手(shi)采集者烂JJ