<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>一知半解</title>
        <link>https://oi8io.cn/</link>
        <description>Recent content on 一知半解</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <copyright>CC BY-NC-SA 4.0</copyright>
        <lastBuildDate>Tue, 28 Jul 2020 11:22:51 +0800</lastBuildDate><atom:link href="https://oi8io.cn/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>git子模块 submodule 使用</title>
            <link>https://oi8io.cn/posts/git-submodule-usage/</link>
            <pubDate>Tue, 28 Jul 2020 11:22:51 +0800</pubDate>
            <guid>https://oi8io.cn/posts/git-submodule-usage/</guid>
            <description>&lt;p&gt;最近真是为了笔记犯愁，平时零零散散记录了笔记，没时间整理，也没时间看，主要是也没有地方看。主要原因是我采用Quiver作为平时记笔记的软件，但是不支持手持设备同步。最近准备整理整理笔记，把笔记发到博客中。由于很久之前采用hexo，而且自己很久不维护了，导致昨天生成文件的时候没有html产生，用debug也看不出毛病。随即怒换hugo。hugo发布和主题都采用git submodule功能，顺便记录之。&lt;/p&gt;&#xA;&lt;h2 id=&#34;主项目初始化&#34;&gt;主项目初始化&#xA;&lt;/h2&gt;&lt;p&gt;git 初始化如下：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git init &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 编写几个文件&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git add .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git commit -m &lt;span class=&#34;s2&#34;&gt;&amp;#34;xxxx&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git remote set-url origin git@github.com/foo/bar.git&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git origin remote set-url git@github.com/foo/bar.git //same as before&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git push&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;通过以上命令可以得到一个空项目。接下来就在该空项目上面使用git子模块submodule功能。&lt;/p&gt;&#xA;&lt;h2 id=&#34;引入子模块&#34;&gt;引入子模块&#xA;&lt;/h2&gt;&lt;p&gt;引入git子模块submodule采用以下三个步骤：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;先采用add命令添加相应的仓库到本地目录&lt;/li&gt;&#xA;&lt;li&gt;init初始化&lt;/li&gt;&#xA;&lt;li&gt;update更新&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;具体例子如下：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git submodule add -b master git@github.com/foo/baz.git subdir&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# hugo举例主题例子&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git submodule add https://github.com/reuixiy/hugo-theme-meme.git themes/meme&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git submodule init&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git submodule update&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h3 id=&#34;存储结构&#34;&gt;存储结构&#xA;&lt;/h3&gt;&lt;p&gt;初始化完成后看看配置文件：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cat .gitmodules&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;应该得到如下信息；这里用hugo的meme主题举例子&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[submodule &amp;#34;themes/meme&amp;#34;]&#xA;&#x9;path = themes/meme&#xA;&#x9;url = https://github.com/reuixiy/hugo-theme-meme.git&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cat .git/config&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;获得内容如下：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[submodule &amp;#34;themes/meme&amp;#34;]&#xA;&#x9;url = https://github.com/reuixiy/hugo-theme-meme.git&#xA;&#x9;active = true&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查看子模块的git信息，跟.git目录一致。是不是瞬间开启套娃模式&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ls -al .git/modules&#xA;ls -al  submodule #子模块所在目录&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;删除子模块&#34;&gt;删除子模块&#xA;&lt;/h2&gt;&lt;p&gt;如果配置错误，没有采用git命令删除的，则可能会出现&lt;code&gt;already exists in the index&lt;/code&gt;，这样只需要检查以上的文件是否存在相关信息，删除账号就可以重新建立submodule了&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git submodule deinit themes/ananke&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Submodule &lt;span class=&#34;s1&#34;&gt;&amp;#39;themes/ananke&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;https://github.com/budparr/gohugo-theme-ananke.git&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; unregistered &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; path &lt;span class=&#34;s1&#34;&gt;&amp;#39;themes/ananke&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 删除目录文件&#xA;git rm --cached themes/ananke&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://git-scm.com/book/en/v2/Git-Tools-Submodules&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;see more&lt;/a&gt;&lt;/p&gt;</description>
        </item><item>
            <title>解决 RHEL 7/ CentOS 7/Fedora 出现Unit iptables.service failed to load</title>
            <link>https://oi8io.cn/posts/rhel-7-iptables-service/</link>
            <pubDate>Sun, 29 Mar 2015 12:43:37 +0000</pubDate>
            <guid>https://oi8io.cn/posts/rhel-7-iptables-service/</guid>
            <description>&lt;p&gt;一直用CentOS 6 习惯了，一下没适应过来。防火墙配置后执行service iptables save 出现&amp;quot;Failed to restart iptables.service: Unit iptables.service failed to load: No such file or directory.&amp;ldquo;错误,在CentOS 7或RHEL 7或Fedora中防火墙由firewalld来管理，当然你可以还原传统的管理方式。或则使用新的命令进行管理。&#xA;假如采用传统请执行一下命令：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;systemctl stop firewalld&#xA;systemctl mask firewalld&#xA;&lt;/pre&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;并且安装iptables-services：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;yum install iptables-services&lt;/pre&gt;&#xA;&lt;p&gt;设置开机启动：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;systemctl enable iptables&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;systemctl [stop|start|restart] iptables&#xA;#or&#xA;service iptables [stop|start|restart]&#xA;&lt;/pre&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;service iptables save&#xA;#or&#xA;/usr/libexec/iptables/iptables.init save&lt;/pre&gt;</description>
        </item><item>
            <title>解决VPN服务器出现PTY read or GRE write failed问题</title>
            <link>https://oi8io.cn/posts/slove-pptpd-vpn-pty-read-or-gre-write-failed/</link>
            <pubDate>Sun, 29 Mar 2015 12:27:48 +0000</pubDate>
            <guid>https://oi8io.cn/posts/slove-pptpd-vpn-pty-read-or-gre-write-failed/</guid>
            <description>&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;http://www.vkilo.com/install-pptp-vpn-rhel-linux.html&#34;  title=&#34;如何在RHEL/Centos/Fedora/下搭建vpn pptp 服务器&#34;&#xA;     target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;在REHL系搭建pptp vpn服务器&lt;/a&gt; 连接的时候出现（619等错误）查看系统日志[cat /var/log/messages |grep pptpd]后发现每次连接失败都会出现以下日志内容:&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;GRE: read(fd=6,buffer=80504c0,len=8196) from PTY failed: status = -1 error = Input/output error, usually caused by unexpected termination of pppd, check option syntax and pppd logs&#xA;CTRL: PTY read or GRE write failed (pty,gre)=(6,7)&#xA;CTRL: Reaping child PPP[13354]&#xA;CTRL: Client XXX.XXX.XXX.XXX control connection finished&lt;/pre&gt;&#xA;&lt;p&gt;于是把打开调试模式，修改/etc/ppp/pptp-options 文件，找到&lt;/p&gt;&#xA;&lt;div class=&#34;wp_codebox&#34;&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;#取消如下行前#&#xA;debug&#xA;#执行&#xA;service pptpd restart&lt;/pre&gt;&#xA;&lt;/div&gt;&#xA;取消行前的注释，重启pptpd服务进入调试模式&#xA;&lt;p&gt;分析日志后发现是logwtmp版本的与pptpd版本不一致的原因导致的问题，于是打开/etc/pptpd.conf文件,找到&lt;/p&gt;&#xA;&lt;div class=&#34;wp_codebox&#34;&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;logwtmp&lt;/pre&gt;&#xA;注释掉logwtmp后，重新启动pptpd，再次连接后一切恢复正常。&#xA;&lt;/div&gt;&#xA;默认启用了proxyarp（在/etc/ppp/pptp-options中）功能，每次非正常断开连接后，执行以下命令：&#xA;&lt;div class=&#34;wp_codebox&#34;&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;#windows &#xA;arp -d&#xA;#linux&#xA;sudo arp -d -a&lt;/pre&gt;&#xA;&amp;nbsp;&#xA;&lt;/div&gt;</description>
        </item><item>
            <title>如何在RHEL/Centos/Fedora/下搭建vpn pptp 服务器</title>
            <link>https://oi8io.cn/posts/install-pptp-vpn-rhel-linux/</link>
            <pubDate>Sun, 29 Mar 2015 12:16:17 +0000</pubDate>
            <guid>https://oi8io.cn/posts/install-pptp-vpn-rhel-linux/</guid>
            <description>&lt;p&gt;用vpn已经有很多年，然而一直因为懒惰原因，所以一直都没有写关于如何搭建vpn服务器的文章，今年兴致所致，分享一下个人搭建vpn server的过程，写的简陋，请勿拍砖。vpn的使用非常广泛，可谓大多网虫和技术股都需要用到的东西，不过看下文之前请先看看自己的服务器是否支持pptp方式的vpn服务器，具体请执行命令&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;modprobe ppp-compress-18 &amp;amp;&amp;amp; echo ok&lt;/pre&gt;&#xA;&lt;p&gt;假如输出ok请继续， 假如不ok，说明服务器不支持。下面的文章可能对你没啥用。&lt;/p&gt;&#xA;&lt;h2 id=&#34;第一步安装pptpd&#34;&gt;第一步：安装pptpd&#xA;&lt;/h2&gt;&lt;p&gt;通常情况下可以通过yum直接安装pptpd，执行&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;yum list pptpd&#xA;&lt;/pre&gt;&#xA;&lt;p&gt;假如有则执行&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;yum install pptpd&#xA;&lt;/pre&gt;&#xA;&lt;p&gt;如果没有需要到sf.net下载，执行如下命令进行安装&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;cd /usr/local/src&#xA;&#xA;#For 64bit OS&#xA;wget http://poptop.sourceforge.net/yum/stable/packages/pptpd-1.4.0-1.el6.x86_64.rpm&#xA;rpm -Uhv pptpd-1.4.0-1.el6.x86_64.rpm&#xA;&#xA;#For 32bit os&#xA;wget http://poptop.sourceforge.net/yum/stable/packages/pptpd-1.4.0-1.el6.i686.rpm&#xA;rmp -Uhv pptpd-1.4.0-1.el6.i686.rpm&lt;/pre&gt;&#xA;&lt;p&gt;到此pptpd vpn 服务器安装完毕&lt;/p&gt;&#xA;&lt;h2 id=&#34;pptp-vpn服务器配置&#34;&gt;pptp vpn服务器配置&#xA;&lt;/h2&gt;&lt;h3 id=&#34;配置pptp-vpn-ip地址&#34;&gt;配置pptp vpn ip地址&#xA;&lt;/h3&gt;&lt;h3 id=&#34;编辑etcpptpdconf设置&#34;&gt;编辑/etc/pptpd.conf设置：&#xA;&lt;/h3&gt;&lt;pre class=&#34;lang:default decode:true&#34;&gt;vim /etc/pptpd.conf&lt;/pre&gt;&#xA;&lt;p&gt;找到39行logwtmp处前面加上#号注释（详细见：&lt;a class=&#34;link&#34; href=&#34;http://www.vkilo.com/slove-pptpd-vpn-pty-read-or-gre-write-failed.html&#34;  title=&#34;解决VPN服务器出现PTY read or GRE write failed问题&#34;&#xA;     target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;解决VPN服务器出现PTY read or GRE write failed问题&lt;/a&gt;）;并且设置本地ip（localip）和客户端ip（remoteid）分配ip大约在102行&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true &#34;&gt;#logwtmp&#xA;&#xA;localip 192.168.0.1&#xA;remoteip 192.168.0.234-238,192.168.0.245&#xA;&lt;/pre&gt;&#xA;&lt;p&gt;这样在pptp  vpn 服务器上面ip为192.168.0.1进行转发，客户端可以分配ip号段为remoteip，根据自己的数量需要设置ip号段。&lt;/p&gt;&#xA;&lt;h3 id=&#34;添加pptp-vpn账户和密码&#34;&gt;添加pptp vpn账户和密码&#xA;&lt;/h3&gt;&lt;h3 id=&#34;编辑etcpppchap-secrets添加格式为&#34;&gt;编辑/etc/ppp/chap-secrets，添加格式为：&#xA;&lt;/h3&gt;&lt;p&gt;用户名       pptpd的名称（默认为pptpd）密码       ip地址&lt;/p&gt;&#xA;&lt;p&gt;这里需要注意：位置一定不能弄错，最后一个ip地址随机分配请填写*,但是一定要加上，否则在验证的时候会出错具体示例如下：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;# client        server  secret                  IP addresses&#xA;vpnuser0        pptpd   vpnpass1                  *&#xA;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;配置pptp-vpn-dns服务器&#34;&gt;配置pptp vpn dns服务器&#xA;&lt;/h3&gt;&lt;p&gt;通常情况下使用google的DNS服务器，编辑/etc/ppp/options.pptpd文件&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;vim /etc/ppp/options.pptpd&#xA;#把ms-dns处修改为：&#xA;&#xA;ms-dns 8.8.8.8&#xA;ms-dns 4.2.2.2&#xA;&#xA;#推荐把调试模式开启，取消以下文字前面的#号取消注释&#xA;debug&lt;/pre&gt;&#xA;&lt;h3 id=&#34;开启网络转发功能&#34;&gt;开启网络转发功能&#xA;&lt;/h3&gt;&lt;pre class=&#34;lang:default decode:true&#34;&gt;#打开 /etc/sysctl.conf&#xA;vim /etc/sysctl.conf&#xA;#添加（如果有则去掉前面的#号取消注释）&#xA;net.ipv4.ip_forward = 1&#xA;#执行如下命令使刚刚操作在系统生效&#xA;sysctl -p&lt;/pre&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;h2 id=&#34;pptp-vpn防火墙配置&#34;&gt;pptp vpn防火墙配置&#xA;&lt;/h2&gt;&lt;p&gt;通过以上步骤基本上可以连接到重启后的vpn服务器，但是要让外部用户能连接&lt;span lang=&#34;EN-US&#34;&gt;PPTP VPN&lt;/span&gt;，还需要在防火墙中将&lt;span lang=&#34;EN-US&#34;&gt;Linux&lt;/span&gt;服务器的&lt;span lang=&#34;EN-US&#34;&gt;1723&lt;/span&gt;端口和&lt;span lang=&#34;EN-US&#34;&gt;47&lt;/span&gt;端口打开，并打开&lt;span lang=&#34;EN-US&#34;&gt;GRE&lt;/span&gt;协议：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;#注意下面的eth1为网卡，通常有一张内网卡和外网卡，请通过ifconfig命令查看&#xA;#请选择显示为外网ip的网卡&#xA;iptables -A INPUT -i eth1 -p tcp --dport 1723 -j ACCEPT&#xA;iptables -A INPUT -i eth1 -p gre -j ACCEPT&#xA;iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE&#xA;#保存防火墙设置并重启防火墙&#xA;service iptables save&#xA;service iptables restart&lt;/pre&gt;&#xA;&lt;p&gt;如果出现&amp;quot;Failed to restart iptables.service: Unit iptables.service failed to load: No such file or directory.&amp;quot; 请查看&lt;a class=&#34;link&#34; href=&#34;http://www.vkilo.com/rhel-7-centos-7-fedora-firewalld-to-iptables-service.html&#34;  title=&#34;解决 RHEL 7/ CentOS 7/Fedora 找不到iptables service&#34;&#xA;     target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;解决 RHEL 7/ CentOS 7/Fedora 找不到iptables service&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;调试pptp-vpn服务器&#34;&gt;调试pptp vpn服务器&#xA;&lt;/h2&gt;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;#开启pptpd&#xA;service pptpd restart&#xA;#设置开机启动pptpd&#xA;chkconfig pptpd on&#xA;&lt;/pre&gt;&#xA;&lt;p&gt;到以上步骤，基本上配置已经完成。接下来连接客户端并执行如下命令查看pptp vpn服务器日志&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true &#34;&gt;tail -f /var/log/messages&lt;/pre&gt;&#xA;&lt;p&gt;假如正常，便可收工，如果有问题，请根据日志提示自动爬文&lt;/p&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;</description>
        </item><item>
            <title>解决LC IS UPDATE SITEMAP WHEN POST</title>
            <link>https://oi8io.cn/posts/baidu-sitemap-generator-illegal-string-offset-lc-is-update-sitemap-when-post/</link>
            <pubDate>Tue, 24 Mar 2015 14:39:44 +0000</pubDate>
            <guid>https://oi8io.cn/posts/baidu-sitemap-generator-illegal-string-offset-lc-is-update-sitemap-when-post/</guid>
            <description>&lt;p&gt;如何解决BAIDU SITEMAP GENERATOR插件出现 ILLEGAL STRING OFFSET LC_IS_UPDATE_SITEMAP_WHEN_POST问题呢？当发布文章的时候，出现了这个，于是便有了下文。 ILLEGAL STRING OFFSET   这个错误请看鸟哥的《&lt;a class=&#34;link&#34; href=&#34;http://www.laruence.com/2011/12/19/2409.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;PHP5.4更新注意点&lt;/a&gt;》&lt;/p&gt;&#xA;&lt;p&gt;wordpress网址地图插件现在用得比较多的就是柳城的《&lt;a class=&#34;link&#34; href=&#34;http://www.liuzhishi.com/314.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Baidu Sitemap Generator&lt;/a&gt;》，我现在用的也是这个！但是有时候会报一个这样的问题！在发布或更新文章，出现的 PHP Warning:Illegal string offset ‘ lc_is_update_sitemap_when_post ’ in ……/wp-content/plugins/baidu-sitemap-generator/baidu_sitemap.php on line 406， 出现这问题的解决办法是：&#xA;打开 baidu-sitemap.php 文件中的第 406 行：&#xA;把下面的代码：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true &#34;&gt;if($get_baidu_sitemap_options[&#39; lc_is_update_sitemap_when_post &#39;] == ’1′){&#xA;    wp_clear_scheduled_hook(‘do_baidu_sitemap_by_post’);&#xA;    wp_clear_scheduled_hook(‘do_this_auto_daily’);&#xA;    wp_schedule_single_event(time()+10, ‘do_baidu_sitemap_by_post’);&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;直接把条件语句注释掉， 改为：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;//if($get_baidu_sitemap_options[&#39; lc_is_update_sitemap_when_post &#39;] == ’1′){&#xA;wp_clear_scheduled_hook(‘do_baidu_sitemap_by_post’);&#xA;wp_clear_scheduled_hook(‘do_this_auto_daily’);&#xA;wp_schedule_single_event(time()+10, ‘do_baidu_sitemap_by_post’);&#xA;//}&lt;/pre&gt;&#xA;&lt;p&gt;就行了。&lt;/p&gt;&#xA;&lt;p&gt;修改后的代码大致意思是：每当发布文章时，sitemap都会自动更新。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>Sublime Text 2/3安装与注册及使用</title>
            <link>https://oi8io.cn/posts/sublime-text-23-install-and-crack-and-use/</link>
            <pubDate>Sat, 31 May 2014 20:02:05 +0000</pubDate>
            <guid>https://oi8io.cn/posts/sublime-text-23-install-and-crack-and-use/</guid>
            <description>&lt;p&gt;久闻sublime text editor 是个神器，其实平时很少用，今天闲来无事儿，特地安装尝试一下，果断各种黑&lt;/p&gt;&#xA;&lt;h2 id=&#34;1sublime-text安装&#34;&gt;1.Sublime Text 安装&#xA;&lt;/h2&gt;&lt;p&gt;下载地址：http://www.sublimetext.com/&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;tar -jxf tar -jxf Sublime\ Text\ 2.0.2\ x64.tar.bz2&#xA;mv Sublime\ Text\ 2 /usr/local/sublime&#xA;ln -s /usr/local/sublime/sublime_text /usr/bin/sublime&#xA;#假如为Sublime text 3 安装于/opt/sublime_text_3&#xA;vim /usr/bin/subl&#xA;#输入以下内容并保存&#xA;#!/bin/bash&#xA;&#xA;SUBLIME_HOME=&#34;/opt/sublime_text&#34;&#xA;LD_LIB=$SUBLIME_HOME/libsublime-imfix.so&#xA;sh -c &#34;LD_PRELOAD=$LD_LIB $SUBLIME_HOME/sublime_text $@&#34;&#xA;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;2sublime-text注册与破解&#34;&gt;2.Sublime Text 注册与破解&#xA;&lt;/h2&gt;&lt;p&gt;安装16进制编辑器&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;yum install ghex&#xA;ghex /usr/local/sublime/sublime_text&lt;/pre&gt;&#xA;&lt;p&gt;在菜单悬在[Edit]-&amp;gt;[Replace]&lt;/p&gt;&#xA;&lt;p&gt;找到&lt;/p&gt;&#xA;&lt;p&gt;33 42&lt;/p&gt;&#xA;&lt;p&gt;替换为&lt;/p&gt;&#xA;&lt;p&gt;32 42&#xA;选择Replace All&lt;/p&gt;&#xA;&lt;p&gt;保存退出（[File]&amp;gt;[Save]-&amp;gt;[Exit]）&lt;/p&gt;&#xA;&lt;p&gt;打开sublime&lt;/p&gt;&#xA;&lt;p&gt;点击菜单[Help]-&amp;gt;[Enter License]&lt;/p&gt;&#xA;&lt;p&gt;输入以下License&#xA;sublime text 2&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;—–BEGIN LICENSE—–&#xA;Patrick Carey&#xA;Unlimited User License&#xA;EA7E-18848&#xA;4982D83B6313800EBD801600D7E3CC13&#xA;F2CD59825E2B4C4A18490C5815DF68D6&#xA;A5EFCC8698CFE589E105EA829C5273C0&#xA;C5744F0857FAD2169C88620898C3845A&#xA;1F4521CFC160EEC7A9B382DE605C2E6D&#xA;DE84CD0160666D30AA8A0C5492D90BB2&#xA;75DEFB9FD0275389F74A59BB0CA2B4EF&#xA;EA91E646C7F2A688276BCF18E971E372&#xA;—–END LICENSE—–&#xA;&lt;/pre&gt;&#xA;&lt;p&gt;sublime text 3&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;----- BEGIN LICENSE ----&#xA;Andrew Weber&#xA;Single User License&#xA;EA7E-855605&#xA;813A03DD 5E4AD9E6 6C0EEB94 BC99798F&#xA;942194A6 02396E98 E62C9979 4BB979FE&#xA;91424C9D A45400BF F6747D88 2FB88078&#xA;90F5CC94 1CDC92DC 8457107A F151657B&#xA;1D22E383 A997F016 42397640 33F41CFC&#xA;E1D0AE85 A0BBD039 0E9C8D55 E1B89D5D&#xA;5CDB7036 E56DE1C0 EFCC0840 650CD3A6&#xA;B98FC99C 8FAC73EE D2B95564 DF450523&#xA;------ END LICENSE ------&lt;/pre&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;点击[Use License]&lt;/p&gt;&#xA;&lt;h2 id=&#34;3sublime-text中文输入法问题&#34;&gt;3.Sublime Text中文输入法问题&#xA;&lt;/h2&gt;&lt;p&gt;Fcitx输入法无法在Sublime Text 中输入中文的解决办法如下：&#xA;新建sublime-imfix.c文件&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;vim sublime-imfix.c&lt;/pre&gt;&#xA;&lt;p&gt;粘帖以下代码到sublime-imfix.c&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:c++ decode:true&#34;&gt;/*&#xA;sublime-imfix.c&#xA;Use LD_PRELOAD to interpose some function to fix sublime input method support for linux.&#xA;By Cjacker Huang&#xA;&#xA;gcc -shared -o libsublime-imfix.so sublime-imfix.c `pkg-config --libs --cflags gtk+-2.0` -fPIC&#xA;LD_PRELOAD=./libsublime-imfix.so subl&#xA;*/&#xA;#include &amp;lt;gtk/gtk.h&amp;gt;&#xA;#include &amp;lt;gdk/gdkx.h&amp;gt;&#xA;typedef GdkSegment GdkRegionBox;&#xA;&#xA;struct _GdkRegion&#xA;{&#xA;  long size;&#xA;  long numRects;&#xA;  GdkRegionBox *rects;&#xA;  GdkRegionBox extents;&#xA;};&#xA;&#xA;GtkIMContext *local_context;&#xA;&#xA;void&#xA;gdk_region_get_clipbox (const GdkRegion *region,&#xA;            GdkRectangle    *rectangle)&#xA;{&#xA;  g_return_if_fail (region != NULL);&#xA;  g_return_if_fail (rectangle != NULL);&#xA;&#xA;  rectangle-&amp;gt;x = region-&amp;gt;extents.x1;&#xA;  rectangle-&amp;gt;y = region-&amp;gt;extents.y1;&#xA;  rectangle-&amp;gt;width = region-&amp;gt;extents.x2 - region-&amp;gt;extents.x1;&#xA;  rectangle-&amp;gt;height = region-&amp;gt;extents.y2 - region-&amp;gt;extents.y1;&#xA;  GdkRectangle rect;&#xA;  rect.x = rectangle-&amp;gt;x;&#xA;  rect.y = rectangle-&amp;gt;y;&#xA;  rect.width = 0;&#xA;  rect.height = rectangle-&amp;gt;height;&#xA;  //The caret width is 2;&#xA;  //Maybe sometimes we will make a mistake, but for most of the time, it should be the caret.&#xA;  if(rectangle-&amp;gt;width == 2 &amp;amp;&amp;amp; GTK_IS_IM_CONTEXT(local_context)) {&#xA;        gtk_im_context_set_cursor_location(local_context, rectangle);&#xA;  }&#xA;}&#xA;&#xA;//this is needed, for example, if you input something in file dialog and return back the edit area&#xA;//context will lost, so here we set it again.&#xA;&#xA;static GdkFilterReturn event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer im_context)&#xA;{&#xA;    XEvent *xev = (XEvent *)xevent;&#xA;    if(xev-&amp;gt;type == KeyRelease &amp;amp;&amp;amp; GTK_IS_IM_CONTEXT(im_context)) {&#xA;       GdkWindow * win = g_object_get_data(G_OBJECT(im_context),&#34;window&#34;);&#xA;       if(GDK_IS_WINDOW(win))&#xA;         gtk_im_context_set_client_window(im_context, win);&#xA;    }&#xA;    return GDK_FILTER_CONTINUE;&#xA;}&#xA;&#xA;void gtk_im_context_set_client_window (GtkIMContext *context,&#xA;          GdkWindow    *window)&#xA;{&#xA;  GtkIMContextClass *klass;&#xA;  g_return_if_fail (GTK_IS_IM_CONTEXT (context));&#xA;  klass = GTK_IM_CONTEXT_GET_CLASS (context);&#xA;  if (klass-&amp;gt;set_client_window)&#xA;    klass-&amp;gt;set_client_window (context, window);&#xA;&#xA;  if(!GDK_IS_WINDOW (window))&#xA;    return;&#xA;  g_object_set_data(G_OBJECT(context),&#34;window&#34;,window);&#xA;  int width = gdk_window_get_width(window);&#xA;  int height = gdk_window_get_height(window);&#xA;  if(width != 0 &amp;amp;&amp;amp; height !=0) {&#xA;    gtk_im_context_focus_in(context);&#xA;    local_context = context;&#xA;  }&#xA;  gdk_window_add_filter (window, event_filter, context);&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;保存并退出&#xA;编译代码，先安装支持库，然后编译，并且拷贝到安装目录下&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;yum install gtk3 gtk2 gtk3-devel gtk2-devel&#xA;gcc -shared -o libsublime-imfix.so sublime-imfix.c `pkg-config --libs --cflags gtk+-2.0` -fPIC&#xA;cp libsublime-imfix.so /usr/local/sublime/lib/&lt;/pre&gt;&#xA;&lt;p&gt;将编译好的扩展文件加入到参数中就会见到奇迹&lt;/p&gt;&#xA;&lt;h2 id=&#34;4设置&#34;&gt;4.设置&#xA;&lt;/h2&gt;&lt;h3 id=&#34;启动图标&#34;&gt;启动图标&#xA;&lt;/h3&gt;&lt;p&gt;上面我们已经编译好了输入法支持的扩展，现在通过启动参数加进来，具体操作如下&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;sublime /usr/share/applications/sublime.desktop&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;[Desktop Entry]&#xA;Version=2.0.2&#xA;Name=Sublime Text 2&#xA;# Only KDE 4 seems to use GenericName, so we reuse the KDE strings.&#xA;# From Ubuntu&#39;s language-pack-kde-XX-base packages, version 9.04-20090413.&#xA;GenericName=Text Editor&#xA;&#xA;Exec=bash -c &#39;LD_PRELOAD=/usr/local/sublime/lib/libsublime-imfix.so sublime&#39;&#xA;Terminal=false&#xA;Icon=/usr/local/sublime/Icon/48x48/sublime_text.png&#xA;Type=Application&#xA;Categories=TextEditor;IDE;Development&#xA;X-Ayatana-Desktop-Shortcuts=NewWindow&#xA;&#xA;[NewWindow Shortcut Group]&#xA;Name=New Window&#xA;Exec=bash -c &#39;LD_PRELOAD=/usr/local/sublime/lib/libsublime-imfix.so sublime&#39; -n&#xA;TargetEnvironment=Unity&lt;/pre&gt;&#xA;&lt;p&gt;如果在sublime_text_3中请编辑&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;/usr/share/applications/sublime_text.desktop&lt;/pre&gt;&#xA;&lt;p&gt;修改对应的Exec如下&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;[Desktop Entry]&#xA;[...]&#xA;Exec=env LD_PRELOAD=/opt/sublime_text/libsublime-imfix.so /opt/sublime_text/sublime_text %F&#xA;[...]&#xA;&#xA;[Desktop Action Window]&#xA;[...]&#xA;Exec=env LD_PRELOAD=/opt/sublime_text/libsublime-imfix.so /opt/sublime_text/sublime_text -n&#xA;[...]&#xA;&#xA;[Desktop Action Document]&#xA;[...]&#xA;Exec=env LD_PRELOAD=/opt/sublime_text/libsublime-imfix.so /opt/sublime_text/sublime_text --command new_file&#xA;[...]&lt;/pre&gt;&#xA;&lt;p&gt;保存后就可以输入中文了&lt;/p&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;然后在你的Applications里面会出现Sublime Text菜单&lt;/p&gt;&#xA;&lt;h3 id=&#34;安装-package-control&#34;&gt;安装 Package Control&#xA;&lt;/h3&gt;&lt;p&gt;基本上是必备扩展打开如下网站&#xA;&lt;a class=&#34;link&#34; href=&#34;https://sublime.wbond.net/installation&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://sublime.wbond.net/installation&lt;/a&gt;&#xA;ctrl+`/[View] &amp;gt; [Show Console]&#xA;从网站复制相应版本代码——粘帖——回车&#xA;重启Sublime Text&#xA;安装成功后，接下来安装Emmet（ZenCoding）举例&#xA;快捷键Ctrl + Shift + P 调出输入输入Install 回车，输入 Emmet 重启Sublime Text后便可以使用Emmet（ZenCoding）&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>plupload图片上传插件的使用</title>
            <link>https://oi8io.cn/posts/plupload/</link>
            <pubDate>Wed, 30 Apr 2014 18:05:25 +0000</pubDate>
            <guid>https://oi8io.cn/posts/plupload/</guid>
            <description>&lt;p&gt;plupload算是一个好东西（用过的人都知道），用起来不好不坏的，当然每个插件在使用过程中未必跟业务完全耦合，就看你修改插件让其符合业务还是业务适应插件，这里对plupload作一个简单的介绍和分享一些个人心得。&lt;/p&gt;&#xA;&lt;h3 id=&#34;plupload简介&#34;&gt;plupload简介&#xA;&lt;/h3&gt;&lt;p&gt;Plupload是有TinyMCE的开发者开发的，为您的内容管理系统或是类似上传程序提供一个高度可用的上传插件。Plupload 目前分为一个核心API 和一个jQuery上传队列部件，这样使你可以直接使用或是自己定制。&lt;/p&gt;&#xA;&lt;h3 id=&#34;plupload特性&#34;&gt;plupload特性&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Plupload使用jQuery的组件做为选择文件和上传文件的队列组件。&lt;/li&gt;&#xA;&lt;li&gt;Plupload使用Flash，Silverlight，HTML5，Gears，BrowserPlus、FileUpload上传文件技术引擎。&lt;/li&gt;&#xA;&lt;li&gt;Plupload允许自定义使用Plupload核心API来进行选择文件与上传文件。&lt;/li&gt;&#xA;&lt;li&gt;JavaScript用来激活文件选择对话框。此文件选择对话框是可以设置允许用户选择一个单独的文件或者是多个文件。 选择的的文件类型也是可以被限制的，因此用户只能选择指定的适当的文件，例如jgp;gif。&lt;/li&gt;&#xA;&lt;li&gt;Plupload允许对上传过程中的一些事件进行自定义，写上自己的处理方式。&lt;/li&gt;&#xA;&lt;li&gt;选定的文件的上传和它所在页面、表单是独立的。每个文件都是单独上传的，这就保证了服务端脚本能够在一个时间点更容易地处理单个文件。具体信息可以访问Plupload官方网站：http://www.plupload.com/&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;plupload配置说明&#34;&gt;plupload配置说明&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Browse_button:触发浏览文件按钮标签的唯一id,,在flash、html5、和silverlight中能找到触发事件的源（我理解的，这个参数在队列部件不需要参见）&lt;/li&gt;&#xA;&lt;li&gt;Container: 展现上传文件列表的容器，[默认是body]&lt;/li&gt;&#xA;&lt;li&gt;chunk_size：当上传文件大于服务器接收端文件大小限制的时候，可以分多次请求发给服务器，如果不需要从设置中移出&lt;/li&gt;&#xA;&lt;li&gt;drop_element：当浏览器支持拖拽的情况下，能够文件拖放到你想要的容器ID里&lt;/li&gt;&#xA;&lt;li&gt;file_data_name：设置上传字段的名称。默认情况下被设置为文件。（我试验了没找到该如何使用它，暂且不提）&lt;/li&gt;&#xA;&lt;li&gt;filters:选择文件扩展名的过滤器,每个过滤规则中只有title和ext两项[{title:&amp;rsquo;&amp;rsquo;, extensions:&amp;rsquo;&amp;rsquo;}]&lt;/li&gt;&#xA;&lt;li&gt;flash_swf_url:flash文件地址&lt;/li&gt;&#xA;&lt;li&gt;headers：自定义的插入http请求的键值对&lt;/li&gt;&#xA;&lt;li&gt;max_file_size：最大上传文件大小（格式100b, 10kb, 10mb, 1gb）&lt;/li&gt;&#xA;&lt;li&gt;multipart：布尔值，如果用mutlipart 代替二进制流的方式，在webkit下无法工作&lt;/li&gt;&#xA;&lt;li&gt;multipart_params： 跟 multipart关联在一起的键值&lt;/li&gt;&#xA;&lt;li&gt;multi_selection： 多选对话框&lt;/li&gt;&#xA;&lt;li&gt;resize：修改图片属性 resize: {width: 320, height: 240, quality: 90}&lt;/li&gt;&#xA;&lt;li&gt;runtimes:上传插件初始化选用那种方式的优先级顺序，如果第一个初始化失败就走第二个，依次类推&lt;/li&gt;&#xA;&lt;li&gt;required_features：需要那些特性，才能初始化插件&lt;/li&gt;&#xA;&lt;li&gt;url：上传服务器地址&lt;/li&gt;&#xA;&lt;li&gt;unique_names：是否生成唯一的文件名，避免与服务器文件重名&lt;/li&gt;&#xA;&lt;li&gt;urlstream_upload：布尔值 如果是flash上传应该用URLStream 代替FileReference.upload&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;pluload-api文档&#34;&gt;pluload API文档&#xA;&lt;/h3&gt;&lt;h4 id=&#34;方法列表&#34;&gt;方法列表&#xA;&lt;/h4&gt;&lt;p&gt;方法列表：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Uploader(setting)：创建实例的构造方法&lt;/li&gt;&#xA;&lt;li&gt;bind(event, function[, scope])：绑定事件&lt;/li&gt;&#xA;&lt;li&gt;destroy()：销毁plupload的实例对象&lt;/li&gt;&#xA;&lt;li&gt;uploader.destroy()&lt;/li&gt;&#xA;&lt;li&gt;getFile(id): 获取上传文件信息&lt;/li&gt;&#xA;&lt;li&gt;init:初始化plupload实例，添加监听对象&lt;/li&gt;&#xA;&lt;li&gt;uploader.destroy()&lt;/li&gt;&#xA;&lt;li&gt;refresh：重新实例化uploader&lt;/li&gt;&#xA;&lt;li&gt;removeFile(id):从file中移除某个文件&lt;/li&gt;&#xA;&lt;li&gt;splice(start,length)：从队列中start开始删除length个文件， 返回被删除的文件列表&lt;/li&gt;&#xA;&lt;li&gt;start() 开始上传&lt;/li&gt;&#xA;&lt;li&gt;stop()停止上传&lt;/li&gt;&#xA;&lt;li&gt;unbind(name, function): 接触事件绑定&lt;/li&gt;&#xA;&lt;li&gt;unbindAll()解绑所有事件&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;属性集合&#34;&gt;属性集合&#xA;&lt;/h4&gt;&lt;ul&gt;&#xA;&lt;li&gt;features：uploader中包含那些特性&lt;/li&gt;&#xA;&lt;li&gt;files:当前队列中的文件列表&lt;/li&gt;&#xA;&lt;li&gt;id：uploader实例的唯一id&lt;/li&gt;&#xA;&lt;li&gt;runtime：当前运行环境（是html5、flash等等)&lt;/li&gt;&#xA;&lt;li&gt;state:当前上传进度状态&lt;/li&gt;&#xA;&lt;li&gt;total：当前上传文件的信息集合&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;事件集合&#34;&gt;事件集合&#xA;&lt;/h4&gt;&lt;ul&gt;&#xA;&lt;li&gt;BeforeUpload(up, file)：文件上传完之前触发的事件&lt;/li&gt;&#xA;&lt;li&gt;ChunkUploaded(up, file,response)文件被分块上传的事件&lt;/li&gt;&#xA;&lt;li&gt;Destroy(up):uploader的destroy调用的方法&lt;/li&gt;&#xA;&lt;li&gt;Error(up, err)：上传出错的时候触发&lt;/li&gt;&#xA;&lt;li&gt;Fileadded(up, files):用户选择文件时触发&lt;/li&gt;&#xA;&lt;li&gt;FileRemoved(up, files):当文件从上传队列中移除触发&lt;/li&gt;&#xA;&lt;li&gt;FileUploaded(up, file, res):文件上传成功的时候触发&lt;/li&gt;&#xA;&lt;li&gt;Init(up):当初始化的时候触发&lt;/li&gt;&#xA;&lt;li&gt;PostInit(up):init执行完以后要执行的事件触发&lt;/li&gt;&#xA;&lt;li&gt;QueueChanged(up):当文件队列变化时触发&lt;/li&gt;&#xA;&lt;li&gt;Refresh(up):当silverlight/flash或是其他运行环境需要移动的时候触发&lt;/li&gt;&#xA;&lt;li&gt;StateChanged(up)当整个上传队列被改变的时候触发&lt;/li&gt;&#xA;&lt;li&gt;UploadComplete(up,file)当队列中所有文件被上传完时触发&lt;/li&gt;&#xA;&lt;li&gt;UploadFile(up,file)当一个文件被上传的时候触发&lt;/li&gt;&#xA;&lt;li&gt;UploadProgress(up,file):当文件正在被上传中触发&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;应用实例&#34;&gt;应用实例&#xA;&lt;/h3&gt;&lt;h3 id=&#34;&#34;&gt;&#xA;&lt;/h3&gt;&lt;p&gt;1.hmtl部分&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:xhtml decode:true&#34;&gt;&amp;lt;div class=&#34;form-group&#34;&amp;gt;&#xA;    &amp;lt;label class=&#34;control-label col-md-2&#34;&amp;gt;缩略图&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;/label&amp;gt;&#xA;    &amp;lt;div class=&#34;col-10&#34;&amp;gt;&#xA;        &amp;lt;div class=&#34;col-md-4&#34; id=&#34;filelist&#34;&amp;gt;&#xA;            &amp;lt;input type=&#34;text&#34; name=&#34;thumbimg&#34; class=&#34;form-control col-md-2&#34;/&amp;gt;&#xA;            &amp;lt;label for=&#34;none&#34; class=&#34;control-label processbar col-md-1&#34;&amp;gt;&amp;lt;/label&amp;gt;&#xA;        &amp;lt;/div&amp;gt;&#xA;        &amp;lt;div id=&#34;uploader&#34; class=&#34;col-md-5&#34;&amp;gt;&#xA;            &amp;lt;button type=&#34;button&#34; id=&#34;pickfiles&#34; class=&#34;btn blue&#34;&amp;gt;选择图片&amp;lt;/button&amp;gt;&#xA;            &amp;lt;button type=&#34;button&#34; id=&#34;uploadfiles&#34; class=&#34;btn default&#34;&amp;gt;上传文件&amp;lt;/button&amp;gt;&#xA;            &amp;lt;pre id=&#34;console&#34; class=&#34;display-hide&#34;&amp;gt;&amp;lt;/pre&amp;gt;&#xA;        &amp;lt;/div&amp;gt;&#xA;    &amp;lt;/div&amp;gt;&#xA;&amp;lt;/div&amp;gt;&lt;/pre&gt;&#xA;&lt;p&gt;2.js部分&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:js decode:true&#34;&gt;   $(function () {&#xA;        var uploader = new plupload.Uploader({&#xA;            runtimes: &#39;html5,flash,silverlight,html4&#39;,&#xA;            browse_button: &#39;pickfiles&#39;, // you can pass in id...&#xA;            container: document.getElementById(&#39;uploader&#39;), // ... or DOM Element itself&#xA;            url: &#39;/extend/common/upload&#39;,&#xA;            flash_swf_url: &#39;/assets/plugins/plupload/Moxie.swf&#39;,&#xA;            silverlight_xap_url: &#39;/assets/plugins/plupload/Moxie.xap&#39;,&#xA;&#xA;            filters: {&#xA;                max_file_size: &#39;10mb&#39;,&#xA;                mime_types: [&#xA;                    {title : &#34;Image files&#34;, extensions : &#34;jpg,gif,png&#34;},&#xA;                    {title : &#34;Zip files&#34;, extensions : &#34;zip&#34;}&#xA;                ]&#xA;            },&#xA;            init: {&#xA;                PostInit: function () {&#xA;                    $(&#39;#uploadfiles&#39;).html(&#34;上传文件&#34;);&#xA;                    $(&#34;#uploadfiles&#34;).on(&#39;click&#39;, function () {&#xA;                        uploader.start();&#xA;                        return false;&#xA;                    });&#xA;                },&#xA;                FilesAdded: function (up, files) {&#xA;                    var html = &#34;&#34;;&#xA;                    plupload.each(files, function (file) {&#xA;&#xA;                        html = &#39;&amp;lt;input type=&#34;text&#34; name=&#34;thumbimg&#34; class=&#34;form-control &#39;+file.id+&#39;&#34; value=&#34;&#39; + file.name + &#39;&#34;/&amp;gt;&amp;lt;label for=&#34;none&#34; class=&#34;control-label processbar col-md-1 &#39; + file.id + &#39;&#34; &amp;gt;&amp;lt;/label&amp;gt;&#39;;&#xA;                    });&#xA;                    $(&#34;#filelist&#34;).html(html);&#xA;                },&#xA;&#xA;                UploadProgress: function (up, file) {&#xA;                    $(&#34;label.&#34; + file.id).html(file.percent + &#39;%&#39;);&#xA;                },&#xA;                FileUploaded: function (up, file,response) {&#xA;                    var res = $.parseJSON(response.response);&#xA;                    $(&#34;input.&#34; + file.id).val(res.result);&#xA;                },&#xA;                Error: function (up, err) {&#xA;                    document.getElementById(&#39;console&#39;).innerHTML += &#34;\nError #&#34; + err.code + &#34;: &#34; + err.message;&#xA;                }&#xA;            }&#xA;        });&#xA;        uploader.init();&#xA;    });&lt;/pre&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;</description>
        </item><item>
            <title>解决fedora/CentOS下不能挂载NTFS分区</title>
            <link>https://oi8io.cn/posts/slv-fedora-centos-mount-ntfs-error/</link>
            <pubDate>Thu, 24 Apr 2014 23:03:11 +0000</pubDate>
            <guid>https://oi8io.cn/posts/slv-fedora-centos-mount-ntfs-error/</guid>
            <description>&lt;p&gt;进了Windows 8 再一次进入Fedora后，出现unable to mount NTFS partition fedora的错误，其实是Windows 8 快速启动造成的。关闭即可。具体操作如下：&lt;/p&gt;&#xA;&lt;p&gt;打开&lt;strong&gt;Control Panel&lt;/strong&gt; 点击 &lt;strong&gt;Power Options&lt;/strong&gt;;&lt;/p&gt;&#xA;&lt;p&gt;点击&lt;strong&gt;Choose what the power buttons do&lt;/strong&gt;;&#xA;点击** Change settings that are currently unavailable**;&#xA;在 &lt;strong&gt;Shutdown&lt;/strong&gt; 设置, 去掉勾选 &lt;strong&gt;Turn on fast startup&lt;/strong&gt;然后点击&lt;strong&gt;Save changes&lt;/strong&gt; 按钮保存.&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>php 实时输出显示</title>
            <link>https://oi8io.cn/posts/php-show-in-time/</link>
            <pubDate>Thu, 24 Apr 2014 22:52:57 +0000</pubDate>
            <guid>https://oi8io.cn/posts/php-show-in-time/</guid>
            <description>&lt;p&gt;网上找了许多办法都行不通，经过半天的折腾。终于弄出来下面能够实时显示当前时间&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;?php&#xA;//ob_end_flush(); //关闭php缓存，或者在flush前ob_flush();&#xA;&#xA; //ie下 需要先发送256个字节, firefox 1024, chrome 2048&#xA; date_default_timezone_set(&#34;PRC&#34;);//设置当前时区&#xA;set_time_limit(0);&#xA;&#xA;for($i=1; $i&amp;lt;=10; $i++)&#xA;{&#xA;    ob_end_clean();&#xA;    ob_start();&#xA;    echo str_repeat(&#34; &#34;, 4096);&#xA;    echo &#34;Now is :&#34;. date(&#34;H:i:s&#34;).&#34;&amp;lt;br&amp;gt;&#34;;&#xA;    echo str_repeat(&#34; &#34;, 4096);&#xA;    ob_flush(); //把php缓存推送到apache去，前面已经关闭了php缓存了，这里再推就报错了&#xA;//    flush(); //把apache缓存推送到浏览器去&#xA;    sleep(1);&#xA;}&lt;/pre&gt;</description>
        </item><item>
            <title>linux 通过bind下搭建DNS Server</title>
            <link>https://oi8io.cn/posts/config-dns-server-on-linux-var-bind/</link>
            <pubDate>Thu, 24 Apr 2014 22:42:47 +0000</pubDate>
            <guid>https://oi8io.cn/posts/config-dns-server-on-linux-var-bind/</guid>
            <description>&lt;p&gt;作为一个web开发人员，开发过程中肯定有很多项目需要分配不同的域名来访问，这样避免一个localhost不够用和避免加端口各种麻烦，以及子目录超级麻烦等问题。那么很多时候需要在开发环境上门绑定多个域名。假如是一个团队开发。那么每个人都去修改hosts是一件很悲剧的事情，那么你需要的就是一台内部的dns服务器。其实本人对理论这块了解甚少，所以重在实用。&lt;/p&gt;&#xA;&lt;h3 id=&#34;1理论普及&#34;&gt;1.理论普及&#xA;&lt;/h3&gt;&lt;h4 id=&#34;dns服务器分为&#34;&gt;DNS服务器分为:&#xA;&lt;/h4&gt;&lt;ol&gt;&#xA;&lt;li&gt;master（主DNS服务器）：拥有区域数据的文件，并对整个区域数据进行管理。&lt;/li&gt;&#xA;&lt;li&gt;slave(从服务器或叫辅助服务器）：拥有主DNS服力器的区域文件的副 本，辅助主DNS服务器对客户端进行解析，当主DNS服务器坏了后，可以完全接替主服务器的工作。&lt;/li&gt;&#xA;&lt;li&gt;forward:将任何查询请求都转发给其他服务器。起到一个代理的作用。&lt;/li&gt;&#xA;&lt;li&gt;cache:缓存服务器。&lt;/li&gt;&#xA;&lt;li&gt;hint：根DNS internet服务器集。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;2软件安装&#34;&gt;2.软件安装&#xA;&lt;/h3&gt;&lt;pre class=&#34;lang:sh decode:true &#34;&gt;#For Debian/Ubuntu&#xA;apt-get install bind*&#xA;#For CentOS/Fedora/RedHat&#xA;yum install bind*&lt;/pre&gt;&#xA;&lt;p&gt;其他的根据自己的功能需要安装相应的安装包。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3配置&#34;&gt;3.配置&#xA;&lt;/h3&gt;&lt;p&gt;通过以下命令&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true &#34;&gt;cat /etc/sysconfig/named&lt;/pre&gt;&#xA;&lt;p&gt;可以看到系统将named的目录指向哪里。&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true &#34;&gt;/etc/sysconfig/named  #由该文件控制是否动chroot及其他参数&#xA;/etc/named.conf       #配置文件&#xA;/var/named/           #数据库文件（如正向、反向、根文件）存放位置&#xA;/var/run/named:       #named程序默认将pid文件放置此目录下&lt;/pre&gt;&#xA;&lt;p&gt;这里主要需要配置的文件就/etc/named.conf&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;vim /etc/named.conf&#xA;#修改文件 主意any的地方根据自己需要&#xA;options {&#xA;    listen-on port 53 { any; };&#xA;    listen-on-v6 port 53 { ::1; };&#xA;    directory     &#34;/var/named&#34;;&#xA;    dump-file     &#34;/var/named/data/cache_dump.db&#34;;&#xA;    statistics-file &#34;/var/named/data/named_stats.txt&#34;;&#xA;    memstatistics-file &#34;/var/named/data/named_mem_stats.txt&#34;;&#xA;    query-source    port 53;  &#xA;    query-source-v6 port 53;&#xA;    allow-query     { any; };&#xA;};&#xA;logging {&#xA;        channel default_debug {&#xA;                file &#34;data/named.run&#34;;&#xA;                severity dynamic;&#xA;        };&#xA;};&#xA;view localhost_resolver {&#xA;    match-clients         { any; };&#xA;    match-destinations { any; };&#xA;    recursion yes;&#xA;    include &#34;/etc/named.rfc1912.zones&#34;;&#xA;};&lt;/pre&gt;&#xA;&lt;p&gt;假如我想绑定ryan.com到192.168.0.5&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;vim /etc/named.rfc1912.zones&#xA;#附加以下内容并保存&#xA;zone &#34;ryan.com&#34; IN {&#xA;        type master;&#xA;        file &#34;ryan.com.zone&#34;;&#xA;        allow-update { none; };&#xA;};&#xA;zone &#34;ryan.com-arpa&#34; IN {&#xA;        type master;&#xA;        file &#34;ryan.com.arpa&#34;;&#xA;        allow-update { none; };&#xA;};&lt;/pre&gt;&#xA;&lt;p&gt;然后分别新建两个文件&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;vim /var/named/ryan.com.zone&#xA;#插入以下内容并保存&#xA;$TTL 1D&#xA;@       IN SOA  ryan.com.  root. (&#xA;                                        0       ; serial&#xA;                                        1D      ; refresh&#xA;                                        1H      ; retry&#xA;                                        1W      ; expire&#xA;                                        3H )    ; minimum&#xA;@       NS      ryan.com.&#xA;@       A       192.168.1.5&#xA;www     A       192.168.1.5&#xA;*       A       192.168.1.5&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;vim /var/named/ryan.com.arpa&#xA;#插入以下内容并保存&#xA;$TTL 1D&#xA;@       IN SOA  ryan.com.  root. (&#xA;                                        0       ; serial&#xA;                                        1D      ; refresh&#xA;                                        1H      ; retry&#xA;                                        1W      ; expire&#xA;                                        3H )    ; minimum&#xA;@       NS      ryan.com.&#xA;@       A       192.168.1.5&#xA;5       PTR     www.ryan.com.&lt;/pre&gt;&#xA;&lt;p&gt;以上编辑基本上完成了基本配置，接下来修改你机器的域名解析&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34; &gt;vim /etc/resolv.conf&#xA;#修改（没有添加）指向dns所在的机器ip&#xA;nameserver 192.168.0.5&#xA;&lt;/pre&gt; &#xA;&lt;p&gt;到此配置结束。&lt;/p&gt;&#xA;&lt;h3 id=&#34;4测试&#34;&gt;4.测试&#xA;&lt;/h3&gt;&lt;pre class=&#34;lang:default decode:true &#34; &gt;#设置开机启动&#xA;chkconfig named --level 235 on&#xA;#开启dns 服务器&#xA;service named start&#xA;#如已经开启请使用下面的命令重启&#xA;service named restart&lt;/pre&gt; &#xA;&lt;p&gt;然后在终端输入&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34; &gt;nslookup &#xA;#enter进入nslookup的会话后直接输入需要测试的域名看看返回的结果是否正确如：&#xA;vkilo.ryan.com&#xA;&lt;/pre&gt; &#xA;&lt;p&gt;还有一些如dig之类的测试命令，根据个人喜好和要求。还有主从这里就不再累赘。&#xA;&amp;lt; 收工&amp;gt;&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>遍历目录文件编码转换</title>
            <link>https://oi8io.cn/posts/dir-file-iconv/</link>
            <pubDate>Fri, 11 Apr 2014 11:20:40 +0000</pubDate>
            <guid>https://oi8io.cn/posts/dir-file-iconv/</guid>
            <description>&lt;p&gt;遍历当前目录及子目录。把所有的文件转换编码到UTF-8&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true &#34; &gt;&amp;lt; ?php&#xA;//php iconv.php&#xA;//exec it on root dir&#xA;$path = dirname(__FILE__);&#xA;tree($path);&#xA;&#xA;function encodeFiles($fileName)&#xA;{&#xA;//    echo $fileName;&#xA;    if (file_exists($fileName)) {&#xA;        // Read in the contents&#xA;        $res = file_get_contents($fileName);&#xA;        $i = pathinfo($fileName);&#xA;        if(!in_array($i[&#39;extension&#39;],array(&#39;js&#39;,&#39;css&#39;,&#39;php&#39;,&#39;html&#39;,&#39;htm&#39;))){&#xA;            return ;&#xA;        }&#xA;        // Just display on the screen the file being modified&#xA;        echo  $fileName . &#34;---form---&#34;;&#xA;        // Convert the contents&#xA;        echo  $encode = mb_detect_encoding($res, array(&#34;ASCII&#34;, &#34;UTF-8&#34;, &#34;GB2312&#34;, &#34;GBK&#34;));&#xA;        echo &#34;---to---UTF-8!\n&#34;;&#xA;        $res = iconv($encode, &#34;UTF-8&#34;, $res);&#xA;        // Write back out to the same file&#xA;        file_put_contents($fileName, $res);&#xA;    } //&#xA;}&#xA;&#xA;function tree($directory)&#xA;{&#xA;    $mydir = dir($directory);&#xA;    while ($file = $mydir-&amp;gt;read()) {&#xA;        if ((is_dir(&#34;$directory/$file&#34;)) AND ($file != &#34;.&#34;) AND ($file != &#34;..&#34;)) {&#xA;            tree(&#34;$directory/$file&#34;);&#xA;        } else {&#xA;            $file =&#34;$directory/$file&#34;;&#xA;&#xA;//            echo &#34;&amp;lt;li&amp;gt;$file&amp;lt;/li&amp;gt;\n&#34;;&#xA;            if(is_file($file)){&#xA;                encodeFiles($file);&#xA;            }&#xA;        }&#xA;    }&#xA;}&lt;/pre&gt; </description>
        </item><item>
            <title>MySQL 编译安装</title>
            <link>https://oi8io.cn/posts/mysql-compile-on-centos/</link>
            <pubDate>Fri, 08 Nov 2013 00:19:04 +0000</pubDate>
            <guid>https://oi8io.cn/posts/mysql-compile-on-centos/</guid>
            <description>&lt;p&gt;最近各种工作没有状态，本来很想写点心情日志啥的。可惜文笔有限制，就当在这里抱怨一下。MySQL 编译安装各种疼。顺便整理下笔记，不说了。都是泪。&lt;/p&gt;&#xA;&lt;p&gt;－－－－－－－－－－－－－－－土豪金分割线－－－－－－－－－－－－－－－－－－－－&#xA;直入主题：依赖安装&#xA;安装环境：centos 6.4 x86_64&#xA;安装c＋＋编译环境：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true &#34;&gt;&#xA;&#xA;yum install gcc gcc-c++ ncurses-devel&lt;/pre&gt;&#xA;&lt;p&gt;bision：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true &#34;&gt;&#xA;&#xA;cd /usr/local/src &#xA;wget http://ftp.gnu.org/gnu/bison/bison-2.7.1.tar.gz&#xA;tar -zxf bison-2.7.1.tar.gz&#xA;cd bison-2.7.1&#xA;./configure&#xA;make &amp;amp;&amp;amp; sudo make install&#xA;cd ..&lt;/pre&gt;&#xA;&lt;p&gt;cmake：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true &#34;&gt;&#xA;&#xA;wget http://www.cmake.org/files/v2.8/cmake-2.8.11.tar.gz&#xA;tar -zxf cmake-2.8.11.tar.gz&#xA;cd cmake-2.8.11&#xA;./bootstrap&#xA;make&#xA;sudo make install&#xA;或者&#xA;./configure&#xA;gmake&#xA;sudo make install&#xA;cd ..&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;&#xA;&#xA;curl -O http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.12.tar.gz&#xA;tar -zxf mysql-5.6.12&#xA;cd mysql-5.6.12&#xA;&#xA;#添加执行用户名和组&#xA;groupadd mysql&#xA;useradd -g mysql mysql&#xA;&#xA;#开始编译安装&#xA;cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \&#xA;-DMYSQL_UNIX_ADDR=/tmp/mysql.sock \&#xA;-DDEFAULT_CHARSET=utf8 \&#xA;-DDEFAULT_COLLATION=utf8_general_ci \&#xA;-DWITH_EXTRA_CHARSETS=all \&#xA;-DWITH_MYISAM_STORAGE_ENGINE=1 \&#xA;-DWITH_INNOBASE_STORAGE_ENGINE=1 \&#xA;-DWITH_MEMORY_STORAGE_ENGINE=1 \&#xA;-DWITH_READLINE=1 \&#xA;-DENABLED_LOCAL_INFILE=1 \&#xA;-DMYSQL_DATADIR=/var/mysql/data \&#xA;-DMYSQL_USER=mysql&#xA;make -j8&#xA;make install&#xA;&#xA;#改变所有者及控制权限&#xA;chmod +w /usr/local/mysql&#xA;chown -R mysql:mysql /usr/local/mysql&#xA;mkdir -p /var/mysql/&#xA;mkdir -p /var/mysql/data/&#xA;mkdir -p /var/mysql/log/&#xA;chown -R mysql:mysql /var/mysql/&#xA;&#xA;#配置文件及安装服务&#xA;cd support-files/&#xA;cp my-default.cnf  /var/mysql/my.cnf&#xA;cp mysql.server /etc/rc.d/init.d/mysqld&#xA;chmod +x /etc/init.d/mysqld&#xA;chkconfig --level 345 mysqld on&#xA;&#xA;#初始化数据库&#xA;/usr/local/mysql/scripts/mysql_install_db \&#xA;--defaults-file=/etc/my.cnf \&#xA;--basedir=/usr/local/mysql \&#xA;--datadir=/var/mysql/data \&#xA;--user=mysql&#xA;&#xA;#建立软链接&#xA;ln -s /usr/local/mysql/bin/mysqladmin /usr/bin/&#xA;ln -s /usr/local/mysql/bin/mysql /usr/bin/&#xA;&#xA;#启动MySQL服务&#xA;service mysqld start&#xA;#修改root帐户密码&#xA;mysqladmin -u root password 123456&#xA;&#xA;#登陆MySQL&#xA;mysql -uroot -p&#xA;&#xA;#创建一个MySQL 帐户&#xA;CREATE USER &#39;ryan&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;some_pass&#39;;#some_pass就是ryan帐户密码&#xA;&#xA;#对用户ryan进行授权，当然你最好不要这么做&#xA;GRANT ALL PRIVILEGES ON *.* TO &#39;ryan&#39;@&#39;%&#39;  IDENTIFIED BY &#39;some_pass&#39;  WITH GRANT OPTION;&#xA;&#xA;#刷新权限&#xA;flush privileges;&#xA;&#xA;#修改默认的引擎&#xA;set global storage_engine=MYISAM&#xA;set storage_engine=MYISAM&lt;/pre&gt;&#xA;&lt;p&gt;写的简单，很少文字说明，当给自己参考。收工！&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>top命令使用详解</title>
            <link>https://oi8io.cn/posts/top-command-in-linux/</link>
            <pubDate>Sun, 11 Aug 2013 01:02:57 +0000</pubDate>
            <guid>https://oi8io.cn/posts/top-command-in-linux/</guid>
            <description>&lt;h4 id=&#34;top命令基本用法&#34;&gt;top命令基本用法&#xA;&lt;/h4&gt;&lt;p&gt;显示系统当前的进程和其他状况； top是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止该程序为止. 比较准确的说,top命令提供了实时的对系统处理器的状态监视.它将显示系统中CPU最“敏感”的任务列表.该命令可以按CPU使用.内存使用和执行时间对任务进行排序；而且该命令的很多特性都可以通过交互式命令或者在个人定制文件中进行设定.&lt;/p&gt;&#xA;&lt;p&gt;top [-] [d delay] [p pid] [q] [c] [C] [S] [s] [i] [n iter] [b]&#xA;p 仅监视进程给定的进程ID&#xA;d 指定每两次屏幕信息刷新之间的时间间隔。当然用户可以使用s交互命令来改变之。&#xA;q 该选项将使top没有任何延迟的进行刷新。如果调用程序有超级用户权限，那么top将以尽可能高的优先级运行。&#xA;S 指定累计模式。&#xA;C 显示总CPU状态，而不是单个的CPU。此选项仅对SMP系统有效。&#xA;s 使top命令在安全模式中运行。这将去除交互命令所带来的潜在危险。&#xA;i 使top不显示任何闲置或者僵死进程。&lt;/p&gt;&#xA;&lt;h4 id=&#34;top&#34;&gt; &lt;img alt=&#34;top&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;http://www.vkilo.com/wp-content/uploads/2013/08/top.jpg&#34;&gt;&#xA;&lt;/h4&gt;&lt;h4 id=&#34;统计信息区上箭头所指部分&#34;&gt;统计信息区（上箭头所指部分）&#xA;&lt;/h4&gt;&lt;p&gt;前五行是系统整体的统计信息。第一行是任务队列信息，同 uptime 命令的执行结果。其内容如下：&lt;/p&gt;&#xA;&lt;div&gt;&#xA;&lt;table border=&#34;0&#34; cellspacing=&#34;1&#34;&gt;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;01:06:48&lt;/td&gt;&#xA;&lt;td&gt;当前时间&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;up 17 days,  6:21&lt;/td&gt;&#xA;&lt;td&gt;系统运行时间，格式为时:天数，小时:分钟&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;1 user&lt;/td&gt;&#xA;&lt;td&gt;当前登录用户数&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;load average: 0.05, 0.08, 0.03&lt;/td&gt;&#xA;&lt;td&gt;系统负载，即任务队列的平均长度。&#xA;三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值。&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;第二、三行为进程和CPU的信息。当有多个CPU时，这些内容可能会超过两行。内容如下：&#xA;&lt;div&gt;&#xA;&lt;table border=&#34;0&#34; cellspacing=&#34;1&#34;&gt;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Tasks: 53 total&lt;/td&gt;&#xA;&lt;td&gt;进程总数&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;1 running&lt;/td&gt;&#xA;&lt;td&gt;正在运行的进程数&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;52 sleeping&lt;/td&gt;&#xA;&lt;td&gt;睡眠的进程数&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;0 stopped&lt;/td&gt;&#xA;&lt;td&gt;停止的进程数&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;0 zombie&lt;/td&gt;&#xA;&lt;td&gt;僵尸进程数&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Cpu(s): 0.3% us&lt;/td&gt;&#xA;&lt;td&gt;用户空间占用CPU百分比&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;1.0% sy&lt;/td&gt;&#xA;&lt;td&gt;内核空间占用CPU百分比&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;0.0% ni&lt;/td&gt;&#xA;&lt;td&gt;用户进程空间内改变过优先级的进程占用CPU百分比&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;99.8% id&lt;/td&gt;&#xA;&lt;td&gt;空闲CPU百分比&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;0.0% wa&lt;/td&gt;&#xA;&lt;td&gt;等待输入输出的CPU时间百分比&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;0.0% hi&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;0.0% si&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;0.1% st&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;最后两行为内存信息。内容如下：&#xA;&lt;table border=&#34;0&#34; cellspacing=&#34;1&#34;&gt;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Mem: 1048876k total&lt;/td&gt;&#xA;&lt;td&gt;物理内存总量&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;887984k used&lt;/td&gt;&#xA;&lt;td&gt;使用的物理内存总量&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;160592k free&lt;/td&gt;&#xA;&lt;td&gt;空闲内存总量&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;0k buffers&lt;/td&gt;&#xA;&lt;td&gt;用作内核缓存的内存量&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Swap: 2097152k total&lt;/td&gt;&#xA;&lt;td&gt;交换区总量&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;57280k used&lt;/td&gt;&#xA;&lt;td&gt;使用的交换区总量&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;2039872k free&lt;/td&gt;&#xA;&lt;td&gt;空闲交换区总量&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;0k cached&lt;/td&gt;&#xA;&lt;td&gt;缓冲的交换区总量。&#xA;内存中的内容被换出到交换区，而后又被换入到内存，但使用过的交换区尚未被覆盖，&#xA;该数值即为这些**内容已存在于内存中**的交换区的大小。&#xA;相应的内存再次被换出时可不必再对交换区写入。&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h4 id=&#34;进程信息区下箭头指向部分&#34;&gt;进程信息区（下箭头指向部分）&#xA;&lt;/h4&gt;&lt;p&gt;统计信息区域的下方显示了各个进程的详细信息。首先来认识一下各列的含义。&lt;/p&gt;&#xA;&lt;div&gt;&#xA;&lt;table border=&#34;0&#34; cellspacing=&#34;1&#34;&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;序号&lt;/td&gt;&#xA;&lt;td&gt;列名&lt;/td&gt;&#xA;&lt;td&gt;含义&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;a&lt;/td&gt;&#xA;&lt;td&gt;PID&lt;/td&gt;&#xA;&lt;td&gt;进程id&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;b&lt;/td&gt;&#xA;&lt;td&gt;PPID&lt;/td&gt;&#xA;&lt;td&gt;父进程id&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;c&lt;/td&gt;&#xA;&lt;td&gt;RUSER&lt;/td&gt;&#xA;&lt;td&gt;Real user name&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;d&lt;/td&gt;&#xA;&lt;td&gt;UID&lt;/td&gt;&#xA;&lt;td&gt;进程所有者的用户id&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;e&lt;/td&gt;&#xA;&lt;td&gt;USER&lt;/td&gt;&#xA;&lt;td&gt;进程所有者的用户名&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;f&lt;/td&gt;&#xA;&lt;td&gt;GROUP&lt;/td&gt;&#xA;&lt;td&gt;进程所有者的组名&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;g&lt;/td&gt;&#xA;&lt;td&gt;TTY&lt;/td&gt;&#xA;&lt;td&gt;启动进程的终端名。不是从终端启动的进程则显示为 ?&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;h&lt;/td&gt;&#xA;&lt;td&gt;PR&lt;/td&gt;&#xA;&lt;td&gt;优先级&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;i&lt;/td&gt;&#xA;&lt;td&gt;NI&lt;/td&gt;&#xA;&lt;td&gt;nice值。负值表示高优先级，正值表示低优先级&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;j&lt;/td&gt;&#xA;&lt;td&gt;P&lt;/td&gt;&#xA;&lt;td&gt;最后使用的CPU，仅在多CPU环境下有意义&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;k&lt;/td&gt;&#xA;&lt;td&gt;%CPU&lt;/td&gt;&#xA;&lt;td&gt;上次更新到现在的CPU时间占用百分比&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;l&lt;/td&gt;&#xA;&lt;td&gt;TIME&lt;/td&gt;&#xA;&lt;td&gt;进程使用的CPU时间总计，单位秒&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;m&lt;/td&gt;&#xA;&lt;td&gt;TIME+&lt;/td&gt;&#xA;&lt;td&gt;进程使用的CPU时间总计，单位1/100秒&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;n&lt;/td&gt;&#xA;&lt;td&gt;%MEM&lt;/td&gt;&#xA;&lt;td&gt;进程使用的**物理内存**百分比&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;o&lt;/td&gt;&#xA;&lt;td&gt;VIRT&lt;/td&gt;&#xA;&lt;td&gt;进程使用的虚拟内存总量，单位kb。VIRT=SWAP+RES&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;p&lt;/td&gt;&#xA;&lt;td&gt;SWAP&lt;/td&gt;&#xA;&lt;td&gt;进程使用的虚拟内存中，被换出的大小，单位kb。&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;q&lt;/td&gt;&#xA;&lt;td&gt;RES&lt;/td&gt;&#xA;&lt;td&gt;进程使用的、未被换出的物理内存大小，单位kb。RES=CODE+DATA&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;r&lt;/td&gt;&#xA;&lt;td&gt;CODE&lt;/td&gt;&#xA;&lt;td&gt;可执行代码占用的**物理**内存大小，单位kb&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;s&lt;/td&gt;&#xA;&lt;td&gt;DATA&lt;/td&gt;&#xA;&lt;td&gt;可执行代码以外的部分(数据段+栈)占用的**物理**内存大小，单位kb&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;t&lt;/td&gt;&#xA;&lt;td&gt;SHR&lt;/td&gt;&#xA;&lt;td&gt;共享内存大小，单位kb&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;u&lt;/td&gt;&#xA;&lt;td&gt;nFLT&lt;/td&gt;&#xA;&lt;td&gt;页面错误次数&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;v&lt;/td&gt;&#xA;&lt;td&gt;nDRT&lt;/td&gt;&#xA;&lt;td&gt;最后一次写入到现在，被修改过的页面数。&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;w&lt;/td&gt;&#xA;&lt;td&gt;S&lt;/td&gt;&#xA;&lt;td&gt;进程状态。&#xA;**D**=不可中断的睡眠状态&#xA;**R**=运行&#xA;**S**=睡眠&#xA;**T**=跟踪/停止&#xA;**Z**=僵尸进程&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;x&lt;/td&gt;&#xA;&lt;td&gt;COMMAND&lt;/td&gt;&#xA;&lt;td&gt;命令名/命令行&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;y&lt;/td&gt;&#xA;&lt;td&gt;WCHAN&lt;/td&gt;&#xA;&lt;td&gt;若该进程在睡眠，则显示睡眠中的系统函数名&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;z&lt;/td&gt;&#xA;&lt;td&gt;Flags&lt;/td&gt;&#xA;&lt;td&gt;任务标志，参考 sched.h&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h4 id=&#34;更改显示内容左箭头指向光标处&#34;&gt;更改显示内容(左箭头指向光标处)&#xA;&lt;/h4&gt;&lt;p&gt;top命令进入后在未按q退出时，一直会占用一个session，所以你键入任何字符都能作为参数给Top&lt;/p&gt;&#xA;&lt;p&gt;通过 **f **键可以选择显示的内容。按 f 键之后会显示列的列表，按 a-z 即可显示或隐藏对应的列，最后按回车键确定。&lt;/p&gt;&#xA;&lt;p&gt;按 &lt;strong&gt;o&lt;/strong&gt; 键可以改变列的显示顺序。按小写的 a-z 可以将相应的列向右移动，而大写的 A-Z 可以将相应的列向左移动。最后按回车键确定。&lt;/p&gt;&#xA;&lt;p&gt;按大写的 &lt;strong&gt;F&lt;/strong&gt; 或 &lt;strong&gt;O&lt;/strong&gt; 键，然后按 a-z 可以将进程按照相应的列进行排序。而大写的 &lt;strong&gt;R&lt;/strong&gt; 键可以将当前的排序倒转。&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;默认情况下仅显示比较重要的 PID、USER、PR、NI、VIRT、RES、SHR、S、%CPU、%MEM、TIME+、COMMAND 列。可以通过下面的快捷键来更改显示内容。&#xA;&lt;p&gt;&lt;span&gt;Ctrl+L &lt;/span&gt; 擦除并且重写屏幕。&#xA;&lt;span&gt;h或者? &lt;/span&gt;  显示帮助画面，给出一些简短的命令总结说明。&#xA;&lt;span&gt;k &lt;/span&gt; 终止一个进程。系统将提示用户输入需要终止的进程PID，以及需要发送给该进程什么样的信号。一般的终止进程可以使用15信号；如果不能正常结束那就使用信号9强制结束该进程。默认值是信号15。在安全模式中此命令被屏蔽。&#xA;&lt;span&gt;i &lt;/span&gt; 忽略闲置和僵死进程。这是一个开关式命令。&#xA;&lt;span&gt;q &lt;/span&gt; 退出程序。&#xA;&lt;span&gt;r &lt;/span&gt; 重新安排一个进程的优先级别。系统提示用户输入需要改变的进程PID以及需要设置的进程优先级值。输入一个正值将使优先级降低，反之则可以使该进程拥有更高的优先权。默认值是10。&#xA;&lt;span&gt;S &lt;/span&gt;切换到累计模式。&#xA;&lt;span&gt;s &lt;/span&gt;改变两次刷新之间的延迟时间。系统将提示用户输入新的时间，单位为s。如果有小数，就换算成m s。输入0值则系统将不断刷新，默认值是5 s。需要注意的是如果设置太小的时间，很可能会引起不断刷新，从而根本来不及看清显示的情况，而且系统负载也会大大增加。&#xA;&lt;span&gt;f或者F&lt;/span&gt; 从当前显示中添加或者删除项目。&#xA;&lt;span&gt;o或者O&lt;/span&gt; 改变显示项目的顺序。&#xA;&lt;span&gt;l &lt;/span&gt; 切换显示平均负载和启动时间信息。&#xA;&lt;span&gt;m &lt;/span&gt; 切换显示内存信息。&#xA;&lt;span&gt;t &lt;/span&gt; 切换显示进程和CPU状态信息。&#xA;&lt;span&gt;c &lt;/span&gt; 切换显示命令名称和完整命令行。&#xA;&lt;span&gt;M &lt;/span&gt; 根据驻留内存大小进行排序。&#xA;&lt;span&gt;P &lt;/span&gt; 根据CPU使用百分比大小进行排序。&#xA;&lt;span&gt;T &lt;/span&gt; 根据时间/累计时间进行排序。&#xA;&lt;span&gt;W &lt;/span&gt; 将当前设置写入~/:toprc文件中。这是写top配置文件的推荐方法。&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;</description>
        </item><item>
            <title>魔兽与PHP设计模式</title>
            <link>https://oi8io.cn/posts/php-design-pattern-with-warcraft/</link>
            <pubDate>Sat, 03 Aug 2013 00:42:13 +0000</pubDate>
            <guid>https://oi8io.cn/posts/php-design-pattern-with-warcraft/</guid>
            <description>&lt;p&gt;此处省略无数字&lt;/p&gt;&#xA;&lt;h3 id=&#34;一单件模式&#34;&gt;一、单件模式：&#xA;&lt;/h3&gt;&lt;p&gt;问题的提出：某些应用程序资源是独占的，因为有且只有一个此类型的资源。例如，通过数据库句柄到数据库的连接是独占的。您希望在应用程序中共享数据库句柄，因为在保持连接打开或关闭时，它是一种开销，在获取单个页面的过程中更是如此。&#xA;问题的解决：那么下面我们就开始玩魔兽吧。首先双击war3.exe，这时候就开始运行魔兽了。我们用代码来实现吧。。&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class War3&#xA;{&#xA;    public function __construct()&#xA;    {&#xA;        echo &#34;War3 is Running.&#34;;&#xA;    }&#xA;}&#xA;&#xA;$war = new War3();&lt;/pre&gt;&#xA;&lt;p&gt;运行！很好，输出War3 is Running.我们已经可以开始游戏了，但是，如果我在代码末尾再加入&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;$war2 = new War3();&#xA;$war3 = new War3();&lt;/pre&gt;&#xA;&lt;p&gt;会怎么样呢？我们试试，输出结果：War3 is Running.War3 is Running.War3 is Running.完了，如果不小心双击了两次就开了3个魔兽，那如果再双击几次，那电脑肯定爆掉。。。我们还是来想想解决方法吧。。。既然我们不能这么随意的就把这个类实例化了，那么我们就把构造函数改成私有方法。&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class War3 {&#xA;    private function __construct() {&#xA;        echo &#34;War3 is Running.&#34;;&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;可是私有变量外部是无法访问的，这样以来，我们就连一个都打不开了啊。别急，我们再给他加一个不用通过实例化，外部也能访问的函数，那就是静态函数&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class War3&#xA;{&#xA;    private function __construct()&#xA;    {&#xA;        echo &#34;War3 is Running.&#34;;&#xA;    }&#xA;&#xA;    public static function runWar()&#xA;    {&#xA;&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;通过这个静态的方法runWar()我们来控制类War3的实例化，那么还缺上一个标识，我们再创建一个标识，通过这个标识来表示我们的类是否已经实例化，如果实例化，直接返回句柄就行了。把类修改成&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class War3&#xA;{&#xA;    protected static $_instance = null;&#xA;&#xA;    private function __construct()&#xA;    {&#xA;        echo &#34;War3 is Running.&#34;;&#xA;}&#xA;&#xA;    public static function runWar()&#xA;    {&#xA;        if (null === self::$_instance) {&#xA;            self::$_instance = new self();&#xA;        }&#xA;&#xA;        return self::$_instance;&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;当然，我们运行魔兽时的实例化也要换种方法，就通过&#xA;$war = War3: :runWar();&#xA;就能开始玩魔兽了，好了，下面把完整的代码附上来：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;?php&#xA;class War3&#xA;{&#xA;    protected static $_instance = null;&#xA;&#xA;    private function __construct()&#xA;    {&#xA;        echo &#34;War3 is Running.&#34;;&#xA;    }&#xA;&#xA;    public static function runWar()&#xA;    {&#xA;        if (null === self::&#xA;                $_instance&#xA;        ) {&#xA;            self::&#xA;                $_instance = new self();&#xA;        }&#xA;        return self::$_instance;&#xA;    }&#xA;}&#xA;&#xA;$war = War3::runWar();&#xA;$war2 = War3::runWar();&#xA;$war3 = War3::runWar();&lt;/pre&gt;&#xA;&lt;p&gt;运行一下，结果是：War3 is Running.太好了，我双击了这么多次，也就只运行了一个魔兽，现在随便你怎么打开，机子都不会爆掉了。这就是传说中的单价模式，主要用于一些很占资源的而且实例仅有一个实例就够用的东西，比如，zendframework中的Zend_Controller_Front前端控制器，就是采用单价模式来设计的，大家有兴趣的话可以看看那个。&lt;/p&gt;&#xA;&lt;h3 id=&#34;二策略模式&#34;&gt;二、策略模式：&#xA;&lt;/h3&gt;&lt;p&gt;问题的提出：在此模式中，算法是从复杂类提取的，因而可以方便地替换。例如，如果要更改搜索引擎中排列页的方法，则策略模式是一个不错的选择。思考一下搜索引擎的几个部分——一部分遍历页面，一部分对每页排列，另一部分基于排列的结果排序。在复杂的示例中，这些部分都在同一个类中。通过使用策略模式，您可将排列部分放入另一个类中，以便更改页排列的方式，而不影响搜索引擎的其余代码。&#xA;问题的解决：呵呵，不讲那么复杂，刚才魔兽好不容易打开了，我们还是玩魔兽好了。下面我们选battle，哇好多种族啊，有人族（Human），兽族（ORC），暗夜精灵族（Nighy Elf），不死族（Undead）。我选精灵族（Nighy Elf），再选一个精灵族和两个兽族（ORC），一个兽族和我是一家的，另一个精灵族和兽族是另一家的。每一个玩家在进入游戏后都会得到一些资源，如一个大厅，五个小精灵（苦工）和一个矿山。这些可以称为是初始化的一些东西，这里我们就可以用到策略模式来封装这些初始化。进入正题，首先我们来构建一个玩家类：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class player&#xA;{ //玩家名字 &#xA;    protected $_name; //种族 &#xA;    protected $_race; //队伍 &#xA;    protected $army; //建筑 &#xA;    protected $building; //人口 &#xA;    protected $population; //黄金 &#xA;    protected $gold; //木材 &#xA;    protected $wood; //构造函数，设定所属种族 &#xA;    public function __construct($race)&#xA;    {&#xA;        $this-&amp;gt;race = $race;&#xA;&#xA;    }&#xA;&#xA;    //__get()方法用来获取保护属性&#xA;    private function __get($property_name)&#xA;    {&#xA;        if (isset($this-&amp;gt;$property_name)) {&#xA;            return ($this-&amp;gt;$property_name);&#xA;        } else {&#xA;            return (NULL);&#xA;        }&#xA;    }&#xA;&#xA;    //__set()方法用来设置保护属性&#xA;    private function __set($property_name, $value)&#xA;    {&#xA;        $this-&amp;gt;$property_name = $value;&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;接着，我们再建一个玩家初始化的接口，&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;?php&#xA;interface initialPlayer&#xA;{ //制造初始化的部队 &#xA;    public function giveArmy($player); //制造初始化的建筑 &#xA;    public function giveBuilding($player); //初始化资源 &#xA;    public function giveSource($player);&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;好了，到这里我们就该对这个接口来实现了，为了方便，我只选了两个种族，就只写这两个种族的初始化了：首先是精灵族：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class NighyElfInitial implements initialPlayer&#xA;{&#xA;//制造初始化的部队&#xA;    public function giveArmy($player)&#xA;    {&#xA;//五个小精灵&#xA;        for ($i = 0; $i &amp;lt;= 5; $i++) {&#xA;            $creator = new CreatArms(); //这个是创建部队类，在后面得工厂模式中会用到，这里我就不多说了 $player - &amp;gt;army[] = $creator - &amp;gt;Creat(&#39;Wisp&#39;, &#39;./Arms/&#39;);&#xA;        }&#xA;    }&#xA;&#xA;//制造初始化的建筑&#xA;    public function giveBuilding($player)&#xA;    {&#xA;        $creator = new CreatBuildings();&#xA;//一个基地&#xA;        $player-&amp;gt;building[] = $creator-&amp;gt;Creat(&#39;TownHall&#39;, &#39;./Buildings/&#39;);&#xA;//一个矿场&#xA;        $player-&amp;gt;building[] = $creator-&amp;gt;Creat(&#39;Mine&#39;, &#39;./Buildings/&#39;);&#xA;    }&#xA;&#xA;//初始化人口上限&#xA;    public function giveSource($player)&#xA;    {&#xA;        $player-&amp;gt;population = 10;&#xA;        $player-&amp;gt;gold = 1000;&#xA;        $player-&amp;gt;wood = 100;&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;接下来是兽族：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class ORCInitial implements initialPlayer&#xA;{&#xA;//制造初始化的部队&#xA;    public function giveArmy($player)&#xA;    {&#xA;//五个苦工&#xA;        for ($i = 0; $i &amp;lt;= 5; $i++) {&#xA;            $creator = new CreatArms(); //这个是创建部队类，在后面得工厂模式中会用到，这里我就不多说了 $player - &amp;gt;army[] = $creator - &amp;gt;Creat(&#39;Peon&#39;, &#39;./Arms/&#39;);&#xA;        }&#xA;    }&#xA;&#xA;//制造初始化的建筑&#xA;    public function giveBuilding($player)&#xA;    {&#xA;&#xA;        $creator = new CreatBuildings();&#xA;//一个基地&#xA;        $player-&amp;gt;building[] = $creator-&amp;gt;Creat(&#39;TownHall&#39;, &#39;./Buildings/&#39;);&#xA;//一个矿场&#xA;        $player-&amp;gt;building[] = $creator-&amp;gt;Creat(&#39;Mine&#39;, &#39;./Buildings/&#39;);&#xA;    }&#xA;&#xA;//初始化人口上限&#xA;    public function giveSource($player)&#xA;    {&#xA;        $player-&amp;gt;population = 10;&#xA;        $player-&amp;gt;gold = 1000;&#xA;        $player-&amp;gt;wood = 100;&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;好了，到这里初始化代码就写好了，现在还差一个控制这些初始化得类，也就是封装他们：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class initialController&#xA;{ //构造函数，参数为玩家的数组 &#xA;    public function __construct($playerArray)&#xA;    {&#xA;        foreach ($playerArray as $player) {&#xA;            switch ($player-&amp;gt;race) {&#xA;                case &#39;NighyElf&#39;:&#xA;                    $initialController = new NighyElfInitial();&#xA;                    break;&#xA;                case &#39;ORC&#39;:&#xA;                    $initialController = new ORCInitial();&#xA;                    break;&#xA;            }&#xA;            $initialController-&amp;gt;giveArmy($player);&#xA;            $initialController-&amp;gt;giveBuilding($player);&#xA;            $initialController-&amp;gt;giveSupply($player);&#xA;        }&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;最后就是简单这么一调用，就OK：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php //有两个精灵族两个兽族 &#xA;$playerArray = array(new player(&#39;NighyElf&#39;), new player(&#39;NighyElf&#39;), new player(&#39;ORC&#39;), new player(&#39;ORC&#39;)); //进行初始化工作 &#xA;$initialController = new initialController($playerArray); ?&amp;gt;&lt;/pre&gt;&#xA;&lt;p&gt;这就是策略模式，他将不同情况下的算法封装在一起。Zend framework中的Zend_Application_Resource就是用策略模式来设计的。&lt;/p&gt;&#xA;&lt;h3 id=&#34;三工厂模式&#34;&gt;三、工厂模式：&#xA;&lt;/h3&gt;&lt;p&gt;问题的提出：最初在设计模式一书中，许多设计模式都鼓励使用松散耦合。要理解这个概念，让我们最好谈一下许多开发人员从事大型系统的艰苦历程。在更改一个代码片段时，就会发生问题，系统其他部分——您曾认为完全不相关的部分中也有可能出现级联破坏。该问题在于紧密耦合。系统某个部分中的函数和类严重依赖于系统的其他部分中函数和类的行为和结构。您需要一组模式，使这些类能够相互通信，但不希望将它们紧密绑定在一起，以避免出现联锁。在大型系统中，许多代码依赖于少数几个关键类。需要更改这些类时，可能会出现困难。例如，假设您有一个从文件读取的User类。您希望将其更改为从数据库读取的其他类，但是，所有的代码都引用从文件读取的原始类。这时候，使用工厂模式会很方便。工厂模式是一种类，它具有为您创建对象的某些方法。您可以使用工厂类创建对象，而不直接使用new。这样，如果您想要更改所创建的对象类型，只需更改该工厂即可。使用该工厂的所有代码会自动更改。&#xA;问题的解决：呵呵，估计有些phper没看懂吧，没关系，那是我从其他地方抄的，我们下面还是通过魔兽来进行吧。这一部分，我看都已经有前人写好了，我就基本上照抄了，请前人不要见怪啊。呵呵。前面选了暗夜精灵族（Nighy Elf），和兽族（ORC），因为小精灵（Wisp）能建造建筑，还能自爆。所以根据这个我们下面先写个小精灵（Wisp）的类。&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class Wisp&#xA;{&#xA;    private $mHealthPoint = 120; //这是小精灵的血量&#xA;    private $mArmor = 0; //这是小精灵的护甲&#xA;//小精灵能建造建筑&#xA;    public function Build()&#xA;    {&#xA;        echo &#39;精灵建造建筑咯。&#xA;&#39;;&#xA;    }&#xA;&#xA;//每个小精灵被造出来时还会占用一个人口&#xA;    public function __construct()&#xA;    {&#xA;        echo &#39;你已经建造了一个小精灵。&#xA;&#39;;&#xA;//这里是增加已有人口的代码&#xA;    }&#xA;&#xA;//每个小精灵死亡会减少你占用的人口&#xA;    public function __destruct()&#xA;    {&#xA;//这里是减少已有人口的代码&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;把这些代码放在Arms / Wisp.php中。啊，还有还有，还有苦工（Peon）的类&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class Peon&#xA;{&#xA;    private $mHealthPoint = 250; //这是苦工的血量&#xA;    private $mArmor = 0; //这是苦工的护甲&#xA;//苦工能建造建筑&#xA;    public function Build()&#xA;    {&#xA;        echo &#39;苦工建造建筑咯。&#xA;&#39;;&#xA;    }&#xA;&#xA;//每个苦工被造出来时还会占用一个人口&#xA;    public function __construct()&#xA;    {&#xA;        echo &#39;你已经建造了一个苦工。&#xA;&#39;;&#xA;//这里是增加已有人口的代码&#xA;    }&#xA;&#xA;//每个苦工死亡会减少你占用的人口&#xA;    public function __destruct()&#xA;    {&#xA;&#xA;//这里是减少已有人口的代码&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;把这些代码放在Arms / Peon.php中。等等，这样岂不是很复杂，魔兽里面还有那么多的兵种，另外都还有两个种族，每次创建一个兵就要new一个，要是记不住这个兵的类名，岂不是new不了？而且如果一个兵是一个类，放在一个文件里，那是不是一开始就要把所有的几十上百个文件都include一次啊，那效率可想而知啊。嘿嘿，当然是有解决办法的啊，我们再写一个类把这些类都封装起来，这个把兵种都封装起来的类我们称之为工厂类，他可以像生产产品一样，来创建兵，帮我们对其实例化。下面我们就来看这个类怎么实现吧。&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class CreatArms&#xA;{&#xA;    public function __construct()&#xA;    {&#xA;    }&#xA;&#xA;    public function Creat($arms, $path = &#39;&#39;)&#xA;    {&#xA;        include $path . $arms . &#39;.php&#39;; //包含要这个类的文件&#xA;        return new $arms; //返回你创建的兵种对象的句柄&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt;这样，即使在兵种多样的情况下，我们仍然可以很方便地实例化：$creator = new CreatArms();&#xA;$w1 = $creator - &amp;gt;Creat(&amp;lsquo;兵种名&amp;rsquo;, &amp;lsquo;前缀或路径&amp;rsquo;);&#xA;例如创建小精灵：$creator = new CreatArms(); //不管创建啥，我都只要使用这个类&#xA;$w1 = $creator - &amp;gt;Creat(‘Wisp’, ’. / Arms / ’); //创建一个小精灵&#xA;$w1 - &amp;gt;Build(); //让小精灵造建筑&#xA;这就是传说中的工厂模式，通过工厂模式，对于如论坛那种有很多种用户的，特别是为了以后扩展比较方便的，采用工厂模式，是个很好的解决方法。在zend framework中的Zend_Form、Zend_Filter、Zend_Validate就是用工厂模式来构架的。&lt;/p&gt;&#xA;&lt;h3 id=&#34;四观察者模式&#34;&gt;四、观察者模式：&#xA;&lt;/h3&gt;&lt;p&gt;问题的提出：观察者模式为您提供了避免组件之间紧密耦合的另一种方法。该模式非常简单：一个对象通过添加一个方法（该方法允许另一个对象，即观察者注册自己）使本身变得可观察。当可观察的对象更改时，它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话，而不必了解原因。&#xA;问题的解决：呵呵，上面还是抄的，看不懂没关系，我们今天重点是玩魔兽。已经造了很长时间的兵了，现在可以出去带兵打仗了，如果我去打电脑的兽族，那么电脑与那个兽族同盟的精灵族就会过来帮忙。那么如何让他知道自己的同盟受攻击了呢。现在我们就来讨论这个问题。首先我们写一下结盟的抽象类：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;&#xA;abstract class abstractAlly&#xA;{ //放置观察者的集合，这里以简单的数组来直观演示&#xA;    protected $oberserverCollection; //增加观察者的方法，参数为观察者（也是玩家）&#xA;    public function addOberserver($oberserver)&#xA;    {&#xA;        $this-&amp;gt;oberserverCollection[] = new oberserver($oberserver);&#xA;    }&#xA;&#xA;//将被攻击的电脑的名字通知各个观察者&#xA;    public function notify($beAttackedPlayerName)&#xA;    {&#xA;//把观察者的集合循环&#xA;        foreach ($this-&amp;gt;oberserverCollection as $oberserver) {&#xA;//调用各个观察者的救援函数，参数为被攻击的电脑的名字，if用来排除被攻击的电脑的观察者&#xA;            if ($oberserver-&amp;gt;name != $beAttackedPlayerName) $oberserver -&amp;gt;help($beAttackedPlayerName);&#xA;}&#xA;    }&#xA;&#xA;    abstract public function beAttacked($beAttackedPlayer);&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;下面我们就写具体的结盟类：&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class Ally extends abstractAlly&#xA;{ //构造函数，将所有电脑玩家的名称的数组作为参数&#xA;&#xA;    public function __construct($allPlayer)&#xA;    { //把所有电脑玩家的数组循环&#xA;&#xA;        foreach ($allPlayer as $player) { //增加观察者，参数为各个电脑玩家的名称&#xA;&#xA;            $this-&amp;gt;addOberserver($player);&#xA;        }&#xA;    }&#xA;&#xA;//将被攻击的电脑的名字通知各个观察者&#xA;    public function beAttacked($beAttackedPlayerName)&#xA;    {&#xA;//调用各个观察者的救援函数，参数为被攻击的电脑的名字，if用来排除被攻击的电脑的观察者&#xA;        $this-&amp;gt;notify($beAttackedPlayerName);&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;接着在二、策略模式中我们定义的player类中加入一个help方法&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php&#xA;class ablit&#xA;{&#xA;    public function help($beAttackedPlayerName)&#xA;    {&#xA;        //这里简单的输出，谁去救谁，最后加一个换行，便于显示&#xA;        echo $this-&amp;gt;name . &#34; help&#34; . $beAttackedPlayerName . &#34;&amp;lt;br /&amp;gt;&#34;;&#xA;    }&#xA;}&lt;/pre&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;这样就行了。最后就是仿真了。&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;&amp;lt;?php //先设置敌方电脑 &#xA;$allComputePlayer = array(&#39;NighyElf2&#39;, &#39;ORC2&#39;); //新建电脑结盟 &#xA;$Ally = new Ally($allComputePlayer); //假设我进攻了电脑的兽族 &#xA;$Ally-&amp;gt;beAttacked(&#39;ORC2&#39;);&lt;/pre&gt;&#xA;&lt;p&gt;这样结盟的另一家就能接到通知，去救援。观察者模式主要就是用在这种情况下。可以将某个状态变化立即通知到相关的对象，相关的对象就可以采用相应的策略。例如，zend framework中的Zend_Message就是用的观察者模式。好了，今天就玩到这里，以后有空再和大家一起玩魔兽啊。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>install mail server on centos 5.5</title>
            <link>https://oi8io.cn/posts/install-mail-server-on-centos-5-5/</link>
            <pubDate>Sun, 21 Jul 2013 00:24:19 +0000</pubDate>
            <guid>https://oi8io.cn/posts/install-mail-server-on-centos-5-5/</guid>
            <description>&lt;pre class=&#34;lang:sh decode:true &#34;&gt;yum remove sendmail yum install dovecot yum install postfix&#xA;yum install cyrus-sasl cyrus-sasl-devel cyrus-sasl-gssapi cyrus-sasl-md5 cyrus-sasl-plain&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;#start dovecot config &#xA;#file=/etc/dovecot.conf&#xA;protocols = imap imaps pop3 pop3s #line 20&#xA;default_mail_env = maildir:/home/vmail/%d/%n #line205&#xA;&#xA;first_valid_uid = 89 #line 328 &#xA;ssl_cert_file = /etc/postfix/ssl/smtpd.crt #line 91&#xA;ssl_key_file = /etc/postfix/ssl/smtpd.key #line 92&#xA;ssl_ca_file = /etc/postfix/ssl/cacert.pem #line 105&#xA;mechanisms = plain login&#xA;   passdb sql {&#xA;   # Path for SQL configuration file, see doc/dovecot-sql-example.conf #line 869&#xA;    args = /etc/dovecot-mysql.conf&#xA;   }&#xA;    userdb sql {&#xA;        # Path for SQL configuration file, see doc/dovecot-sql-example.conf #line 931&#xA;        args = /etc/dovecot-mysql.conf&#xA;    }&#xA;    client {&#xA;      # The client socket is generally safe to export to everyone. Typical use&#xA;      # is to export it to your SMTP server so it can do SMTP AUTH lookups&#xA;      # using it.&#xA;      path = /var/spool/postfix/private/auth&#xA;      user = postfix&#xA;      group = postfix&#xA;      mode = 0660&#xA;    }&#xA;#end dovecot config&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true &#34;&gt;#create vmail&#xA;&amp;gt; mkdir /home/vmail &#xA;&amp;gt; chmod 770 /home/vmail &#xA;&amp;gt; chown postfix:postfix /home/vmail&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:tsql decode:true &#34;&gt;#start dovecot-mysql config&#xA;#file=/etc/dovecot-mysql.conf&#xA;driver = mysql&#xA;connect = host=/var/lib/mysql/mysql.sock dbname=postfix user=postfix password=pwd4postfix&#xA;default_pass_scheme = MD5-CRYPT&#xA;user_query = SELECT &#39;/home/vmail/%d/%n&#39; as home, &#39;maildir:/home/vmail/%d/%n&#39; as mail, 89 AS uid, 89 AS gid, concat(&#39;dirsize:storage=&#39;, quota) AS quota FROM mailbox WHERE username = &#39;%u&#39; AND active = &#39;1&#39;&#xA;password_query = SELECT username as user, password, 89 AS uid, 89 AS gid FROM mailbox WHERE username = &#39;%u&#39; AND active = &#39;1&#39;&#xA;#end dovecot-mysql.conf&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;#start postfix config main.cf&#xA;#file = /etc/postfix/main.cf&#xA;mynetworks = 198.71.86.91/32, 127.0.0.0/8, 198.71.86.92/32, 192.80.146.47/32 #line 248&#xA;inet_interfaces = all #line 100&#xA;myhostname = mail.vkilo.com #line 70&#xA;mydomain =vkilo.com #line 71&#xA;#inet_interfaces = localhost #line 103&#xA;&#xA;mydestination = $myhostname, localhost.$mydomain, localhost #line 148&#xA;&#xA;#start virtual_mailbox config append&#xA;virtual_mailbox_base = /home/vmail&#xA;readme_directory = /usr/share/doc/postfix-2.3.3/README_FILES&#xA;virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf, regexp:/etc/postfix/virtual_regexp&#xA;virtual_gid_maps = static:89&#xA;virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf&#xA;virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf&#xA;virtual_minimum_uid = 89&#xA;virtual_transport = virtual&#xA;virtual_uid_maps = static:89&#xA;dovecot_destination_recipient_limit = 1&#xA;smtpd_sasl_auth_enable = yes&#xA;smtpd_sasl_type = dovecot&#xA;smtpd_sasl_path=/var/spool/postfix/private/auth&#xA;smtpd_sasl_local_domain = $myhostname&#xA;smtpd_sasl_security_options = noanonymous&#xA;broken_sasl_auth_clients = yes&#xA;smtpd_sasl_authenticated_header = yes&#xA;smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_non_fqdn_recipient, reject_unknown_recipient_domain&#xA;smtpd_sasl_security_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_non_fqdn_recipient, reject_unknown_recipient_domain&#xA;#smtpd_sasl_security_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination&#xA;smtpd_tls_security_level = may&#xA;smtpd_tls_loglevel = 1&#xA;smtpd_tls_auth_only =yes&#xA;smtp_use_tls = yes&#xA;smtpd_use_tls = yes&#xA;smtp_tls_note_starttls_offer = yes&#xA;smtpd_tls_key_file = /etc/postfix/ssl/smtpd.key&#xA;smtpd_tls_cert_file = /etc/postfix/ssl/smtpd.crt&#xA;#`smtpd_tls_CAfile = /etc/postfix/ssl/cacert.pem&#xA;smtpd_tls_received_header = yes&#xA;smtpd_tls_session_cache_timeout = 3600s&#xA;tls_random_source = dev:/dev/urandom&#xA;smtpd_helo_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_non_fqdn_hostname&#xA;smtpd_sender_restrictions = reject_non_fqdn_sender, reject_unknown_sender_domain&#xA;smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_non_fqdn_recipient, reject_unknown_recipient_domain&#xA;smtpd_helo_required = yes&#xA;unknown_local_recipient_reject_code = 550&#xA;disable_vrfy_command = yes&#xA;smtpd_data_restrictions = reject_unauth_pipelining&#xA;#end postfix config&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;#Afterwards we create the certificates for TLS&#xA;mkdir /etc/postfix/ssl&#xA;cd /etc/postfix/ssl/&#xA;openssl genrsa -des3 -rand /etc/hosts -out smtpd.key 1024&#xA;chmod 600 smtpd.key&#xA;openssl req -new -key smtpd.key -out smtpd.csr&#xA;openssl x509 -req -days 3650 -in smtpd.csr -signkey smtpd.key -out smtpd.crt&#xA;openssl rsa -in smtpd.key -out smtpd.key.unencrypted&#xA;mv -f smtpd.key.unencrypted smtpd.key&#xA;openssl req -new -x509 -extensions v3_ca -keyout cakey.pem -out cacert.pem -days 3650&#xA;#end create certificates&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;#start mysql_virtual_alias_maps.cf&#xA;#file=/etc/postfix/mysql_virtual_alias_maps.cf&#xA;user = postfix&#xA;password = postfixuser&#xA;hosts = localhost&#xA;dbname = postfix&#xA;table = alias&#xA;select_field = goto&#xA;where_field = address&#xA;#end mysql_virtual_alias_maps.cf&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;#start /etc/postfix/mysql_virtual_domains_maps.cf&#xA;#file=/etc/postfix/mysql_virtual_domains_maps.cf&#xA;user = postfix&#xA;password = postfixuser&#xA;hosts = localhost&#xA;dbname = postfix&#xA;table = domain&#xA;select_field = domain&#xA;where_field = domain&#xA;additional_conditions = and backupmx = &#39;0&#39; and active = &#39;1&#39;&#xA;#end&lt;/pre&gt;&#xA;&lt;pre class=&#34;lang:default decode:true &#34;&gt;#vim /etc/postfix/mysql_virtual_mailbox_maps.cf&#xA;hosts = localhost&#xA;user = postfix&#xA;password = postfixuser&#xA;dbname = postfix&#xA;table = mailbox&#xA;select_field = maildir&#xA;where_field = username&#xA;#end&lt;/pre&gt; &#xA;&lt;pre class=&#34;lang:default decode:true &#34; &gt;#vim /usr/lib64/sasl2/smtpd.conf&#xA;#for i586 /usr/lib/sasl2/smtpd.conf&#xA;pwcheck_method: auxprop&#xA;mech_list: PLAIN LOGIN&#xA;auxprop_plugin: sql&#xA;sql_verbose: yes&#xA;sql_engine: mysqli&#xA;sql_hostnames: localhost&#xA;sql_user: postfix&#xA;sql_passwd: postfixuser&#xA;sql_database: postfix&#xA;sql_select: select password from mailbox where username = &#39;%u@%r&#39;&#xA;log_level: 3&#xA;#end&lt;/pre&gt; &#xA;&lt;pre class=&#34;lang:default decode:true &#34; &gt;service postfix start&#xA;service saslauthd start&#xA;chkconfig --level 235 postfix on&#xA;chkconfig --level 235 saslauthd on&#xA;postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf&#xA;postmap -q john@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf&lt;/pre&gt; </description>
        </item><item>
            <title>使用php pdo 连接到mssql sqlsrv </title>
            <link>https://oi8io.cn/posts/connect-to-mssql-using-php-pdo-sqlsrv/</link>
            <pubDate>Fri, 19 Jul 2013 20:43:58 +0000</pubDate>
            <guid>https://oi8io.cn/posts/connect-to-mssql-using-php-pdo-sqlsrv/</guid>
            <description>&lt;p&gt;首先到官方http://msdn.microsoft.com/en-us/sqlserver/ff657782.aspx 下载相应的驱动。&#xA;然后windows为例&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;extension=php_pdo_odbc.dll&#xA;extension=php_pdo_sqlsrv_54_nts.dll&#xA;extension=php_sqlsrv_54_nts.dll&lt;/pre&gt;&#xA;&lt;p&gt;查看phpinfo中是否已经开启MsSQL&#xA;接下来用代码测试即可&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true&#34;&gt;$DSN  = &#34;mssql:host=localhost;dbname=testdb&#34;;//mssql dsn&#xA;$DSN=&#34;sybase:host=localhost;dbname=testdb&#34;;//sybase dsn&#xA;$DSN=&#34;dblib:host=localhost;dbname=testdb&#34;;//any dsn&#xA;$DSN = &#34;sqlsrv:Server=localhost,1521;Database=testdb&#34;;//ms sql server&#xA;$dbUser = &#34;dbuser&#34;;//username&#xA;$dbPass = &#34;password&#34;;//password&#xA;$conn = new PDO($DSN,$dbUser,$dbPass);//connect handle&#xA;$conn-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);// set some attribute of pdo object&#xA;$query = &#34;select * from table where field=:field;&#34;; //T_SQL query &#xA;$fieldValue = &#39;Value&#39;;//&#xA;$params = array(&#34;:field&#34;=&amp;gt;$fieldValue);&#xA;$getProducts = $conn-&amp;gt;prepare($query);&#xA;$getProducts-&amp;gt;execute($params);&#xA;$products= $getProducts-&amp;gt;fetchAll(PDO::FETCH_ASSOC);&lt;/pre&gt;</description>
        </item><item>
            <title>vim 命令与快捷键</title>
            <link>https://oi8io.cn/posts/vim-quick/</link>
            <pubDate>Sun, 07 Jul 2013 14:30:35 +0000</pubDate>
            <guid>https://oi8io.cn/posts/vim-quick/</guid>
            <description>&lt;p&gt;:set nu 设置行号&lt;/p&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;插入命令&lt;/p&gt;&#xA;&lt;p&gt;i：光标后&lt;/p&gt;&#xA;&lt;p&gt;I：行首&lt;/p&gt;&#xA;&lt;p&gt;a:光标前&lt;/p&gt;&#xA;&lt;p&gt;A:行末&lt;/p&gt;&#xA;&lt;p&gt;o:光标后插入新行&lt;/p&gt;&#xA;&lt;p&gt;O:光标上插入新行&lt;/p&gt;&#xA;&lt;p&gt;定位&lt;/p&gt;&#xA;&lt;p&gt;h:left&lt;/p&gt;&#xA;&lt;p&gt;j:down&lt;/p&gt;&#xA;&lt;p&gt;k:up&lt;/p&gt;&#xA;&lt;p&gt;l:right&lt;/p&gt;&#xA;&lt;p&gt;$:行尾&lt;/p&gt;&#xA;&lt;p&gt;0：行首&lt;/p&gt;&#xA;&lt;p&gt;H:(hight)屏幕上端&lt;/p&gt;&#xA;&lt;p&gt;M:(mediun)屏幕中央&lt;/p&gt;&#xA;&lt;p&gt;L:(lower)屏幕下方&lt;/p&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;定位命令&lt;/p&gt;&#xA;&lt;p&gt;:set nu&lt;/p&gt;&#xA;&lt;p&gt;:set nonu&lt;/p&gt;&#xA;&lt;p&gt;gg:到第一行&lt;/p&gt;&#xA;&lt;p&gt;G:到最后一行&lt;/p&gt;&#xA;&lt;p&gt;nG:到第n行&lt;/p&gt;&#xA;&lt;p&gt;:n：到第n行&lt;/p&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;删除命令&lt;/p&gt;&#xA;&lt;p&gt;x:删除光标所在处的字符&lt;/p&gt;&#xA;&lt;p&gt;nx:删除光标所在处后的n个字符&lt;/p&gt;&#xA;&lt;p&gt;dd:删除光标所在行&lt;/p&gt;&#xA;&lt;p&gt;ndd:删除第n行字符&lt;/p&gt;&#xA;&lt;p&gt;gG:删除光标所在到文章底部的内容&lt;/p&gt;&#xA;&lt;p&gt;D:删除光标所在到行首的&lt;/p&gt;&#xA;&lt;p&gt;:n1,n2d:删除n1到n2行的所有内容&lt;/p&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;复制粘贴&lt;/p&gt;&#xA;&lt;p&gt;yy,Y:复制当前行&lt;/p&gt;&#xA;&lt;p&gt;nyy,nY 复制当前行以下n行&lt;/p&gt;&#xA;&lt;p&gt;dd:剪切当前行&lt;/p&gt;&#xA;&lt;p&gt;ndd :剪切当前行以下n行&lt;/p&gt;&#xA;&lt;p&gt;p,P：粘贴在当前光标所在行下或行上&lt;/p&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;查找/替换&lt;/p&gt;&#xA;&lt;p&gt;r:替换光标所在处&lt;/p&gt;&#xA;&lt;p&gt;R:替换光标后的字符直到esc&lt;/p&gt;&#xA;&lt;p&gt;u:取消，上一步ctrl+z(undo)&lt;/p&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;&lt;p&gt;/string: 查找n next，N pre set:ic(忽略大小写)&lt;/p&gt;&#xA;&lt;p&gt;:%s/old/new/g:全文替换&lt;/p&gt;&#xA;&lt;p&gt;：n1,n2s/old/new/g n1 to n2&lt;/p&gt;&#xA;&lt;p&gt;：n1,n2s/old/new/c 询问&lt;/p&gt;&#xA;&lt;p&gt;保存/退出&lt;/p&gt;&#xA;&lt;p&gt;ZZ=:wq&lt;/p&gt;&#xA;&lt;p&gt;:wq! owner root&lt;/p&gt;&#xA;&lt;p&gt;:w dir/filename&lt;/p&gt;&#xA;&lt;p&gt;:r filename 倒入文件内容&lt;/p&gt;&#xA;&lt;p&gt;:r !date 倒入当前日期&lt;/p&gt;&#xA;&lt;p&gt;:map ^p 0x&amp;lt;ESC&amp;gt;&lt;/p&gt;&#xA;&lt;p&gt;^ 行首&lt;/p&gt;&#xA;&lt;p&gt;：n1,n2s/^/#/g 添加行首#&lt;/p&gt;&#xA;&lt;p&gt;：n1,n2s/^#//g 删除行首#&lt;/p&gt;&#xA;&lt;p&gt;特殊字符转义///&lt;/p&gt;&#xA;&lt;p&gt;:ab a b  定义a =b&lt;/p&gt;&#xA;&lt;p&gt;^p = ctrl+v+p&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>windows 8 pid 4 system  80 port </title>
            <link>https://oi8io.cn/posts/windows-8-pid-4-system-80-port/</link>
            <pubDate>Thu, 04 Jul 2013 10:46:51 +0000</pubDate>
            <guid>https://oi8io.cn/posts/windows-8-pid-4-system-80-port/</guid>
            <description>&lt;p&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;Start Command Prompt:&lt;/span&gt;&#xA;1. Hit the combination key of Windows+R (or start run window)&#xA;2. Type cmd and hit enter.&#xA;3. This will open the command prompt&lt;/p&gt;&#xA;&lt;p&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;Check which process is using port 80:&lt;/span&gt;&#xA;1. On the command prompt window, type the following command (copy and paste) without the &amp;quot; &amp;ldquo;.&lt;/p&gt;&#xA;&lt;p&gt;&amp;ldquo;netstat -o -n -a | findstr 0.0:80&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;1. The last column is what is called as the process ID column.&lt;/p&gt;&#xA;&lt;p&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;Open Task Manager to check the process ID:&lt;/span&gt;&#xA;1. Right click on the taskbar to open the the task manager.&#xA;2. Go to the Processes tab.&#xA;3. Click the View menu&#xA;4. And make sure you select the PID (Process Identifier) as shown in the image below.&#xA;5. Now you’ll be able to see which process is using the PID in question. In my case the process ID was 4 which stood for NT AUTHORITY/SYSTEM.&#xA;Do not kill that process! If you do you will get a blue screen of death (BSOD). This is an important process comprised of various services. The service in question is (the one using port 80) “World Wide Web Publishing Service (W3SVC)“. This is the service using port 80. Go to the service and stop it..&lt;/p&gt;&#xA;&lt;p&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;To stop this service:&lt;/span&gt;&#xA;1. Go to Task Manager.&#xA;2. Click the Services tab&#xA;3. Arrange the Services by description.&#xA;4. Look for something that reads World Wide Web Publishing Service in the description column&#xA;5. Right click on it and select Stop Sevice.&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s it, now try and connect with tiny umbrella and you will see that it will not give you the dreaded error that something is using port 80. I do not know how important the W3SVC service is, so, once you finish with tiny umbrella turn it back on again.&lt;/p&gt;&#xA;&lt;p&gt;This tut was not done by me, my only credit is to find it and modify it a bit and posting it here.&lt;/p&gt;&#xA;&lt;p&gt;Hope this helps you guys and if it does you know what to do! PRESS THANKS!&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>article close html tag</title>
            <link>https://oi8io.cn/posts/article-close-html-tag/</link>
            <pubDate>Wed, 03 Jul 2013 03:05:21 +0000</pubDate>
            <guid>https://oi8io.cn/posts/article-close-html-tag/</guid>
            <description>&lt;p&gt;文章关闭标签函数&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:php decode:true &#34;&gt;function CloseTags($html)&#xA;&#xA;{&#xA;&#xA;        // strip fraction of open or close tag from end (e.g. if we take first x characters, we might cut off a tag at the end!)&#xA;    &#xA;        $html = preg_replace(&#39;/&amp;lt;[^&amp;gt;]*$/&#39;,&#39;&#39;,$html); // ending with fraction of open tag&#xA;    &#xA;        // put open tags into an array&#xA;    &#xA;        preg_match_all(&#39;#&amp;lt;([a-z]+)(?: .*)?(?&amp;lt;![/|/ ])&amp;gt;#iU&#39;, $html, $result);&#xA;    &#xA;        $opentags = $result[1];&#xA;    &#xA;        // put all closed tags into an array&#xA;    &#xA;        preg_match_all(&#39;#&amp;lt;/([a-z]+)&amp;gt;#iU&#39;, $html, $result);&#xA;    &#xA;        $closetags = $result[1];&#xA;    &#xA;        $len_opened = count($opentags);&#xA;    &#xA;        // if all tags are closed, we can return&#xA;    &#xA;        if (count($closetags) == $len_opened) {&#xA;    &#xA;            return $html;&#xA;    &#xA;        }&#xA;    &#xA;        // close tags in reverse order that they were opened&#xA;    &#xA;        $opentags = array_reverse($opentags);&#xA;    &#xA;        // self closing tags&#xA;    &#xA;        $sc = array(&#39;br&#39;,&#39;input&#39;,&#39;img&#39;,&#39;hr&#39;,&#39;meta&#39;,&#39;link&#39;);&#xA;    &#xA;        // ,&#39;frame&#39;,&#39;iframe&#39;,&#39;param&#39;,&#39;area&#39;,&#39;base&#39;,&#39;basefont&#39;,&#39;col&#39;&#xA;    &#xA;        // should not skip tags that can have content inside!&#xA;    &#xA;        for ($i=0; $i &amp;lt; $len_opened; $i++)&#xA;    &#xA;        {&#xA;    &#xA;            $ot = strtolower($opentags[$i]);&#xA;    &#xA;            if (!in_array($opentags[$i], $closetags) &amp;amp;&amp;amp; !in_array($ot,$sc))&#xA;    &#xA;            {&#xA;    &#xA;                $html .= &#39;&amp;lt;/&#39;.$opentags[$i].&#39;&amp;gt;&#39;;&#xA;    &#xA;            }&#xA;    &#xA;            else&#xA;    &#xA;            {&#xA;    &#xA;                unset($closetags[array_search($opentags[$i], $closetags)]);&#xA;    &#xA;            }&#xA;    &#xA;        }&#xA;    &#xA;        return $html;&#xA;&#xA;}&lt;/pre&gt;</description>
        </item><item>
            <title>Samsung I9100 Galaxy S II 最简单root方法</title>
            <link>https://oi8io.cn/posts/i9100-root-best-solution/</link>
            <pubDate>Sun, 23 Jun 2013 13:51:05 +0000</pubDate>
            <guid>https://oi8io.cn/posts/i9100-root-best-solution/</guid>
            <description>&lt;p&gt;因为本人没有android设备，更准确说，我没有智能手持设备，故对android设备我果断不熟，每次刷机以及刷机还有刷机都要花良久时间方可完事儿，这里分享一下如何root Samsung I9100 Galaxy S II 获取root权限&#xA;设备上面刷的是官方4.1.2的rom，折腾良久未果，其中原因不说的好，因为存储卡不能用，所以确定改用adb命令来root。开始&lt;/p&gt;&#xA;&lt;h3 id=&#34;1当然要安装驱动&#34;&gt;1.当然要安装驱动&#xA;&lt;/h3&gt;&lt;p&gt;建议去官方网站下载最新驱动&#xA;地址：&lt;a class=&#34;link&#34; href=&#34;http://www.samsung.com/us/support/downloads/global&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;http://www.samsung.com/us/support/downloads/global&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;选择对应型号下载即可。&lt;/p&gt;&#xA;&lt;p&gt;安装驱动时注意查看设备管理器的com端口是否驱动成功，安装后会有Samsung的设备字样，而且不应该有叹号。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2准备root需要的工具&#34;&gt;2. 准备root需要的工具&#xA;&lt;/h3&gt;&lt;p&gt;去&lt;a class=&#34;link&#34; href=&#34;http://pan.baidu.com/share/link?shareid=2123502885&amp;amp;amp;uk=1107686635&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;http://pan.baidu.com/share/link?shareid=2123502885&amp;amp;uk=1107686635&lt;/a&gt;下载&lt;/p&gt;&#xA;&lt;p&gt;adb usb通信命令行工具adbtool.zip 也可以到Google官方下载&lt;a class=&#34;link&#34; href=&#34;https://dl-ssl.google.com/android/repository/tools_r22.0.1-windows.zip&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://dl-ssl.google.com/android/repository/tools_r22.0.1-windows.zip&lt;/a&gt;最新的工具包。&lt;/p&gt;&#xA;&lt;p&gt;当然这都是针对windows的，其他平台MAC/Linux请使用对应的工具。&lt;/p&gt;&#xA;&lt;p&gt;以及拿root权限工具CWM-SuperSU-v0.97.zip(有0.99版本的，我这里为测试)&lt;/p&gt;&#xA;&lt;h3 id=&#34;3现在开始执行root操作&#34;&gt;3.现在开始执行root操作&#xA;&lt;/h3&gt;&lt;p&gt;a.手机链接到电脑，确认已经链接好，使用手机管家之类的进行备份。&lt;/p&gt;&#xA;&lt;p&gt;b.按住Volume 上＋Home键＋power键就是（加音量键＋主页键＋电源键）3秒以上放开，重启后进入recovery模式，选择Install Update with adb，接着手机进入等待传送状态。&lt;/p&gt;&#xA;&lt;p&gt;c.解压adb工具包，将并将CWM-SuperSU-v0.97.zip放入到adb工具对应的目录中&lt;/p&gt;&#xA;&lt;p&gt;打开终端工具（命令行工具），并cd到adb所在目录，当然这里你可以用绝对路径执行adb操作。&lt;/p&gt;&#xA;&lt;p&gt;输入&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:sh decode:true&#34;&gt;adb usb&lt;/pre&gt;&#xA;&lt;p&gt;然后输入&lt;/p&gt;&#xA;&lt;pre class=&#34;lang:default decode:true&#34;&gt;adb sideload CWM-SuperSU-v0.97.zip&lt;/pre&gt;&#xA;&lt;p&gt;这里确保CWM-SuperSU-v0.97.zip 与adb.exe在同一目录。假如不在同一目录请使用相应的路径。&lt;/p&gt;&#xA;&lt;p&gt;输入命令后你可以看到手机屏幕上面有安装的信息，手机重启后任务完成。&lt;/p&gt;&#xA;&lt;p&gt; &lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
