分类 语言编程 下的文章

Movable Type

MT是我使用时间最长的一个博客程序。它基于Perl,功能强大而且可靠性十分稳妥。然而,在快餐文化异常普及的当下,它显得有点疲态百出。它没有php程序的灵活、部署简易,直白点说是折腾。因为站点移到国外的VPS的原因,国内连接速度实在不敢恭维,因此MT也成了我困难丛丛的选择。无奈只能转投效率优先的typecho。

因为博客思路设计的差异,我仅仅转换了原来的文章及相关评论。涉及到的数据表也只有3个。有需要的朋友可以参考下。将下面的源码保存为php文件,放在typecho博客根目录然后运行即可。(建议做好相关数据库备份后,在本地转换成功后再上传)

    <?php
    /**
     * Typecho Blog Platform
     *
     * @copyright  Copyright (c) 2008 Typecho team (http://www.typecho.org)
     * @license    GNU General Public License 2.0
     * @version    $Id: index.php 1153 2017-03-12 10:53:22Z ezo.biz $
     */
    
    /** 载入配置支持 */
    if (!defined('__TYPECHO_ROOT_DIR__') && !@include_once 'config.inc.php') {
        file_exists('./install.php') ? header('Location: install.php') : print('Missing Config File');
        exit;
    }
    
    /** 初始化组件 */
    #Typecho_Widget::widget('Widget_Init');
    $d_MT = "blog";
    /**
     * 初始化mt数据库
     */
    $dbMT = new Typecho_Db('Mysql', 'mt_');
    $dbMT->addServer(array (
       'host' => '127.0.0.1',
       'user' => 'root',
       'password' => '123456',
       'charset' => 'utf8',
       'port' => '3306',
       'database' => $d_MT,
     ), Typecho_Db::READ | Typecho_Db::WRITE);
     Typecho_Db::set($dbMT);
    //清空原有数据
    $db->query("DELETE FROM `typecho_contents`;");
    $db->query("DELETE FROM `typecho_relationships`;");
    $db->query("DELETE FROM `typecho_comments`;");
    
    $a=$dbMT->query("SELECT entry_id,entry_created_on,entry_modified_on,entry_title,Entry_text,entry_text_more,entry_basename FROM mt_entry;");
    $posts = $dbMT->fetchAll($a);
    foreach($posts as $post){
      unset($sql);
      $post['entry_created_on'] = strtotime($post['entry_created_on']);
      $post['entry_modified_on'] = strtotime($post['entry_modified_on']);
      if(!empty($post['entry_text_more']) || ($post['entry_text_more'] !="")){
        $post['Entry_text'] = $post['Entry_text'].$post['entry_text_more'];
      }
      $post['Entry_text'] = preg_replace('/(http|https)(.*?)(ezo\.biz\/b\/).*?(\/)((?:[a-z0-9_-|\.|-]*)(\.)(gif|jpeg|jpg|png))/i', "https://ezo.biz/b_img/$5", $post['Entry_text']);
      $post['Entry_text'] = str_replace("http://ezo.biz","https://ezo.biz",$post['Entry_text']);
      $post['Entry_text'] = str_replace("http://www.ezo.biz","https://www.ezo.biz",$post['Entry_text']);
      $post['Entry_text'] = mysql_real_escape_string($post['Entry_text']);
      $post['entry_title'] = mysql_real_escape_string($post['entry_title']);
    
    
      /**
       * 修复typecho slug主键唯一的问题
       */
      $d = gmdate('Ymd',$post['entry_created_on']);
      $post['entry_basename'] = $post['entry_basename']."-$d";
    
    
      $sql = "INSERT INTO `typecho_contents` (`cid`, `title`, `slug`, `created`, `modified`, `text`, `order`, `authorId`, `template`, `type`, `status`, `password`, `commentsNum`, `allowComment`, `allowPing`, `allowFeed`, `parent`, `views`, `viewsNum`, `likesNum`)  VALUES (NULL, '$post[entry_title]', '$post[entry_basename]', '$post[entry_created_on]', '$post[entry_modified_on]', '$post[Entry_text]', '0', '1', NULL, 'post', 'publish', NULL, '0', '1', '1', '1', '0', '0', '0', '0');";
      //返回文章id
      $cid = $db->query($sql,Typecho_Db::WRITE,Typecho_Db::INSERT);
      //绑定目录
      $db->query("INSERT INTO `typecho_relationships` (`cid`, `mid`) VALUES ('$cid', '1');");
    
      /**
       * 转换评论
       */
      $b = $dbMT->query("SELECT comment_author,comment_created_on,comment_email,comment_entry_id,comment_ip,comment_text,comment_url FROM mt_comment WHERE comment_visible=1 AND comment_entry_id=$post[entry_id];");
      $comments = $dbMT->fetchALL($b);
      foreach ($comments as $comment) {
        # 批量导入评论
        $comment['comment_created_on'] = strtotime($comment['comment_created_on']);
        $db->query("INSERT INTO `typecho_comments` (`coid`, `cid`, `created`, `author`, `authorId`, `ownerId`, `mail`, `url`, `ip`, `agent`, `text`, `type`, `status`, `parent`) VALUES (NULL, '$cid', '$comment[comment_created_on]', '$comment[comment_author]', '0', '0', '$comment[comment_email]', '$comment[comment_url]', '$comment[comment_ip]', NULL, '$comment[comment_text]', 'comment', 'approved', '0');");
      }
    }

ssl.png

因为目前ssl要求比较迫切。很多朋友随便搜索一篇指引文章后就直接抄袭相关配置然后就配置配置出来的ssl虽然表面上看上去没有什么问题,但实际是不规范的。大家可以通过这个网址:https://www.ssllabs.com/ssltest/ 去检测下自己的ssl配置是否科学。

最近爬文发现一个nginx的ssl配置介绍(点击这里查看)感觉不错,按照这个文章指引配置的ssl,在ssl检测一般都能拿到A+这个水平。如果你有多个站点,建议将ssl配置部分做成ssl.conf放在nginx的global文件夹中作为引用文件,真的十分实用。本人的ssl.conf示例如下,大家可以参考下:

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout  10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE:!kEDH;
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /usr/local/nginx/startssl_trust_chain.crt;
    add_header Strict-Transport-Security "max-age=31536000";
    resolver 8.8.8.8 8.8.4.4;

-EOF-


php.jpg

因为typecho的测试版appstore需要使用curl访问https,这个DO主机是15年部署的,当时编译php时候没有考虑为curl增加对https的支持。因此打算更新php顺便将curl也更新了。网上教程很多,随便搜索一下都有很多。我这里就将过程中遇到的几个梗吐槽一下,希望也遇到相似情况的朋友可以少走点弯路。

这个主机是基于Debian 7,web架构是nginx + php (相关操作仅供指引请尽量备份好相关数据),本文是通过编译方式升级php。

准备工作
通过命令行查看PHP编译信息

php -i | grep configure

得到我的主机的php编译信息是这样的

./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-openssl=/usr --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --enable-xml --enable-discard-path --enable-safe-mode --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --with-curlwrappers --enable-mbregex --enable-fastcgi --enable-fpm --enable-force-cgi-redirect --enable-mbstring --with-mcrypt --with-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --disable-ipv6 --without-pear --with-iconv=/usr/local/lib --disable-debug --enable-opcache

下载好新版的php并解压

wget http://php.net/distributions/php-5.6.30.tar.gz
tar -zxvf php-5.6.30.tar.gz
cd php-5.6.30

备份好原来的php防止编译失败可以直接回滚

mv /usr/local/php  /usr/local/php5.3.8  

进行./configure时遇到了第一个梗
如果你不想看编译curl的过程,可以直接跳到梗2看解决办法。
configure就直接报错,提示类似下面的

checking for CURL support... yes
checking for CURL in default path... found in /usr
checking for cURL 7.9.8 or greater... libcurl 7.21.6
checking for curl_easy_perform in -lcurl... no
configure: error: There is something wrong. Please check config.log for more information.

搜索了下说curl版本不对,遂直接下载最新的curl,通过编译(./configure;make && make install)方式升级了curl。重新在php编译目录执行configure,结果依旧上面的报错。

通过命令行curl -V查看curl版本如下

localhost:~ user$ curl -V
curl 7.52.1 (i686-pc-linux-gnu) libcurl/7.21.6

晕死,怎么curl和libucurl的版本不一致的?爬文了半天没有结果。重装了curl几遍还没有结果。后来看了下curl的文档,发现是因为共享库造成的。晕死,curl编译的配置应该是用./configure -disable-shared才对。这样编译出来的curl和libcurl版本才是一致的。通过这样编译后curl -V得到的信息是这样的:

localhost:~ user$ curl -V
curl 7.52.1 (i686-pc-linux-gnu) libcurl/7.52.1

梗2
重新在php编译目录执行configure,结果依旧上面的报错()。上面编译curl的努力不是白费了吗?晕死。。。继续爬文,最后在stackoverflow找到解决问题的方法:重新安装curl-devel或者需要指定curl的安装路径(这个仅适合编译方式安装的curl)

Ubuntu:

sudo apt-get install libcurl4-gnutls-dev

CentOS:

sudo yum install curl-devel

编译方式安装了curl的(我的那种情况):
在php的configure里面加入--with-curl=/usr/local. (/usr/local为你curl安装的路径).

安装完之后,可以到php目录顺利configure了。

准备make,梗三出现了
提示iconv函数不支持。晕死,我之前的php也是编译方式安装的,这个参数也是那样编译出来的。爬文。。。找到两个处理方法,直接在configure参数里面删除iconv,这样就无法使用iconv。

因此我选择了另外一个方法。通过打开php安装目录的Makefile,搜索到EXTRA_LIBS =

-lcrypt -lz -lcrypt -lrt -lmysqlclient -lmcrypt -lltdl -lpng -lz -ljpeg -lcurl -lz -lrt -lm -ldl -lnsl -lrt -lxml2 -lssl -lcrypto -lcurl -lssh2 -lssl -lcrypto -lldap -lz -lrt -lxml2 -lfreetype -lz -lpng16 -lmysqlclient -lm -lrt -ldl -lxml2 -lcrypt -lxml2 -lxml2 -lxml2 -lxml2 -lcrypt

的后面增加-liconv

然后重新make,然后make install,ok了。

弄完后,可以将原来在/usr/local/php/etc/备份的php.ini和php-fpm.ini恢复到当前位置。重启php-fpm即可。
查看curl版本,最新的!
curl.png

-EOF-


wordpress-logo-stacked-rgb.png

貌似2017年1月1日起是http使用的最后期限,所有站点都纷纷开始使用https访问。我最近也使用了acme.sh进行相关站点的https证书处理。但是唯独某个使用wordpress的站点老死无法生成证书,通过acme的debug模式可以看到服务器返回的是403访问拒绝的错误。

通过更换虚拟目录和手工配置验证文件等方法纠错依旧无解。我的主机配置是nginx的PHP方案。后来想了一下是否是nginx配置文件有问题。最终在看wordpress官方的nginx rewrite时发现了问题的端倪。原来在Global restrictions file就是官方推荐的rewrite方案文件wordpress.conf其中有一段:

# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~ /\. {
    deny all;
}

因为ssl证书验证时候创建过程是要通过web方式访问站点根目录中的.well-known目录中生成验证字符串文件。因此这行rewrite导致该目录无法被验证服务访问。但是奇怪的是通过手工创建的文件可以通过http访问(可能是我当时幻觉了╥﹏╥...)。

解决问题的方法很简单,就是将nginx配置文件目录中的wordpress.conf里面找到上面那几行注释掉即可。

具体的设置可以参考hrwhisper的配置方法进行配置Nginx服务器,本机使用的配置文件是这样的,因为多个站点共用了证书生成路径,因此统一写成了ssl-key.conf文件进行配置。ssl.conf文件请详细查看这里
nginx站点的vhost配置文件

server {
        listen 443 ssl;
        server_name www.ezo.biz ezo.biz;
        charset     utf-8;
        index index.html index.htm index.php;
        root  /home/ccchen/www/ezo.biz;
        ssl_certificate /etc/letsencrypt/live/ezo.biz/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/ezo.biz/privkey.pem;
        include global/ssl.conf;

        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.php$1 last;
        }

        location ~ .*\.php(\/.*)*$ {
            #root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi_params;
        }

}
server {
    listen  80;
    server_name ezo.biz www.ezo.biz;
    include global/ssl-key.conf;
}

ssl-key.conf文件

location ^~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /home/ccchen/www/key;
}

location / {
    return 301 https://$server_name$request_uri;
}

BTW:如果日后使用acme.sh进行证书更新的时候切记使用下面的范例进行操作(注意路径):

acme.sh  --issue  -d mydomain.com -d www.mydomain.com  --webroot  /home/ccchen/www/key

其实/home/ccchen/www/key这个路径是所有站点都共用的,你可以自定义自己的路径,记得将改文件夹权限改为可读写。

如果你想独立管理每个站点的ssl证书的话,推荐查看这个文章,有介绍nginx 1.6+后版本的ssl配置。

-EOF-


pjblog.gifASP为基础的PJblog(下简称PJ)可属今年国内发展最快,迅速崛起的blog了.因为本人对asp编写并不熟悉,流于表面简单的测试了一下PJ,功能不算强大.基本的blog分类,发表,编辑,引用,回响,rss...其实都较为普通的.
那么,PJ其实优越在那里呢?仔细发现,PJ的模板是相当漂亮的.无论在多媒体,特别是视听觉媒体,上面做的相当不错.页面元素很丰富.一看上去就让人感觉喜欢的样子.还有结合JS特效处理的效果.等等,都是PJ受到青睐和看好的重要原因.
说了好的,也要来点负面的评论.
其一,PJ在处理绚丽界面的同时忽略了WEB标准,XHTML 1.0 Transitional,也未能完美通过.这是需要改进的.
其二,借鉴boblog的发展经验看.PJ也是处理独立开发过程,PuterJam作为PJ开发的一把手,如果缺乏共同开发团体,当发展到一定阶段,恐怕回出现一定的技术瓶颈.这个是控制产品生命周期的重要制约因素.故此,作为开发人员,不得不考虑的.
其三,ASP本身的制约.使用MDB数据库的PJ,当数据库膨胀到一定程度的时候,是否会成为PJ运行的阻力呢?时候可以考虑静态页面或者采取更优化的存取策略呢?
其四,Blog作为一种share mind的重要平台,过多绚丽的色调,是否会成为资讯传播的阻碍呢?这根平衡木的支点应该摆在什么位置.